您的位置:首页 > 其它

TSOJ1352 线段树区间更新+区间查询

2018-02-13 22:40 381 查看
   从大前天开始系统的学习了一下线段树,总结了一些技巧,刷了几道题- -
   话不多说,开始表演。
       题目大意是初始区间为1,给定区间【l,r】,区间每个数+1。再给m个询问,询问【l,r】区间的和。
    建树。(用模板)

    对于区间更新,我们可以先不更新子区间的值,而是加一个懒惰标记。若更新或查询的是子区间的话,就把懒惰标记往下传,并清空当前节点的标记,再依次push up。
     #include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6+5;
int n,m,t,l,r;

struct node{
int l,r;
long long sum,lazy;
void update(int x)
{
sum += (r-l+1)*x;
lazy += x;
}
}tree[maxn*4];

void push_up(int x)
{
tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
}

void push_down(int x)
{
int lazyval = tree[x].lazy;
if(lazyval){
tree[x<<1].update(lazyval);
tree[x<<1|1].update(lazyval);
tree[x].lazy = 0;
}
}

void build(int x,int l,int r)
{
tree[x].l = l,tree[x].r = r;
tree[x].sum = tree[x].lazy = 0;
if(l==r) tree[x].sum = 0;
else{
int mid = (l+r)/2;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
}
}

void update(int x,int l,int r)
{
int L=tree[x].l,R=tree[x].r;
if(l<=L&&r>=R)
 tree[x].update(1);
else{
push_down(x);
int mid = (L+R)/2;
if(l<=mid)
update(x<<1,l,r);
if(r>mid)
update(x<<1|1,l,r);
push_up(x);
}
}

long long query(int x,int l,int r)
{
int L=tree[x].l,R=tree[x].r;
long long ans = 0;
if(l<=L&&r>=R)
ans += tree[x].sum;
else{
push_down(x);
// cout<<tree[2].sum<<"  id"<<2<<endl;
// cout<<tree[5].sum<<"  id"<<5<<endl;
// cout<<tree[4].sum<<"  id"<<4<<endl;

int mid = (L+R)/2;
if(l<=mid)
ans+=query(x<<1,l,r);
if(r>mid)
ans+=query(x<<1|1,l,r);
push_up(x);
//cout<<ans<<endl;
}
return ans;
}

int main()
{
//freopen("d://test.txt","r",stdin);
while(~scanf("%d%d%d",&n,&m,&t))
{
build(1,1,n);
for(int i=0;i<m;i++)
{
scanf("%d%d", &l, &r);
update(1,l,r);
}
// for(int i=1;i<=n;i++)
// cout<<tree[i].sum<<endl;
for(int i=0;i<t;i++)
{
scanf("%d%d",&l,&r);
cout<<query(1,l,r)<<endl;
}
//cout<<tree[3].sum;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: