HDU 1698 线段树(区间修改)
第一行给出样例个数;
第二行给出hook的个数(全部初始化为1)
第三行给出区间操作的个数
接下来每一行有x,y,z;代表在 区间内的所有hook的数值都改成
.
最后,求出来这些操作之后,所有hook的总和。
//AC
//HDU 1698 线段树(区间查询和修改)
//只要求查询总和 --- tree[1]
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<set>
#include<queue>
#include<stack>
using namespace std;
const int maxn=1e5+5;
int num[maxn];
int tree[maxn<<2];
int mark[maxn<<2];
void pushup(int root)
{
tree[root]=tree[2*root]+tree[2*root+1];
return;
}
void pushdown(int root,int ln,int rn)
{
if(mark[root])
{
tree[2*root]=ln*mark[root];//为什么之前传了value不对呢?应该是mark[]不一定对应当前的value
tree[2*root+1]=rn*mark[root];
mark[2*root]=mark[root];
mark[2*root+1]=mark[root];
mark[root]=0;
}
return;
}
void build(int root,int left,int right)
{
mark[root]=0;
if(left==right)
{
tree[root]=num[left];
return;
}
int mid=(left+right)/2;
build(2*root,left,mid);
build(2*root+1,mid+1,right);
pushup(root);
}
void Update(int root,int uleft,int uright,int left,int right,int value)
{
if(left>uright || right<uleft)//没有交集
return;
if(left>=uleft && right<=uright)//更新后要做的正经事2333,easy to forget
{ //如果在区间内
tree[root]=value*(right-left+1);
mark[root]=value;
return;
}
int mid=(left+right)/2;
pushdown(root,mid-left+1,right-mid);
if(uleft<=mid)
Update(2*root,uleft,uright,left,mid,value);
if(mid<uright)
Update(2*root+1,uleft,uright,mid+1,right,value);
pushup(root);
}
int main()
{
int tcase;
scanf("%d",&tcase);
int tc=1;
while(tcase--)
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
num[i]=1;
build(1,1,n);
// for(int i=1;i<=4*n;i++)
// cout<<tree[i]<<" ";
// cout<<endl;
while(q--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Update(1,x,y,1,n,z);
for(int i=1;i<=4*n;i++)
cout<<tree[i]<<" ";
cout<<endl;
}
printf("Case %d: The total value of the hook is %d.\n",tc++,tree[1]);
}
}
注意pushdown()函数的操作。在下推的过程,不能赋值value的。
很有可能,本来应该下推的,但是由于并不需要更新,就搁置了。如果你用当前的value去更新,可能跟上一次的数值不一样嘛。
是这样理解的不????