您的位置:首页 > 其它

NYOJ 1068 ST(线段树插线问线)

2015-10-12 14:22 344 查看
题目:NYOJ 1068 ST

其实线段树题目贵在对树的操作有一个清晰的认识,那些事需要回溯的时候维护的,那些是可以直接维护的,如果能够直接维护就不要放到回溯的时候,这样操作简单,不容易出错。

比如这道题目,更新的时候是给【 l,r 】都加上一个值val,查询的时候成段查询一段的和喝一段的中奇数的个数。

我们在建树的时候通过回溯求出初始值的和和奇数的个数,然后更新的值就可以直接维护了,每次给某一段加一个值,我们更新到段上面,来保存这个要加的值,然后他的更新延迟到求某段和或者奇数的时候用到的时候更新,这样就很清晰了。

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define Del(a,b) memset(a,b,sizeof(a))
using namespace std;
const long long inf = 0x3f3f3f3f;
const long long N = 1E4 + 100;

struct Node
{
long long l,r;
bool flag;
long long num,sum,cnt;
};
Node tree[4*N];
void yougth(long long o)
{
tree[o].cnt = tree[o+o].cnt + tree[o+o+1].cnt;
tree[o].sum = tree[o+o].sum + tree[o+o+1].sum;
}
void build(long long o,long long l,long long r)
{
tree[o].l = l;
tree[o].r = r;
tree[o].num = tree[o].sum = tree[o].cnt = 0;
tree[o].flag = false;
if(l==r)
{
long long x;
scanf("%lld",&x);
if(x%2)
tree[o].cnt = 1;
tree[o].sum = x;
tree[o].flag = true;
return ;
}
long long mid = (l+r)/2;
build(o+o,l,mid);
build(o+o+1,mid+1,r);
yougth(o);
}
void push_update(long long o)
{
if(tree[o].flag)
{
tree[o].flag = false;
//tree[o+o].num = tree[o+o+1].num = tree[o].num;  SB
tree[o+o].num += tree[o].num;
tree[o+o+1].num += tree[o].num;
tree[o+o].flag = tree[o+o+1].flag = true;
tree[o].num = 0;
}
}
void update(long long o,long long l,long long r,long long x)
{
if(tree[o].l==l && tree[o].r == r)
{
tree[o].num += x;
tree[o].flag = true;
return ;
}
push_update(o);
long long mid=(tree[o].l+tree[o].r)>>1;
if(r<=mid)
update(o+o,l,r,x);
else if(l>mid)
update(o+o+1,l,r,x);
else
{
update(o+o,l,mid,x);
update(o+o+1,mid+1,r,x);
}
}
long long query(long long o,long long l,long long r,bool ok)
{
if(tree[o].l == l && tree[o].r == r && tree[o].flag)
{
long long tmp = tree[o].r-tree[o].l+1;
if(ok)
return tree[o].sum + tmp*tree[o].num;
return tree[o].num%2?(tmp-tree[o].cnt):tree[o].cnt;
}
push_update(o);
long long mid=(tree[o].l+tree[o].r)>>1;
if(r<=mid)
return query(o+o,l,r,ok);
else if(l>mid)
return query(o+o+1,l,r,ok);
else
{
return query(o+o,l,mid,ok) + query(o+o+1,mid+1,r,ok);
}
}
int main()
{
//    freopen("Input.txt","r",stdin);
//    freopen("Out.txt","w",stdout);
long long n,m;
while(~scanf("%lld%lld",&n,&m))
{
build(1,1,n);
while(m--)
{
getchar();
char c[10];;
long long a,b,x;
scanf("%s %lld%lld",c,&a,&b);
long long len = strlen(c);
char flag = '0';
for(long long k=0;k<len;++k)
{
if(c[k]>='A' && c[k]<='Z')
{
flag = c[k];
break;
}
}
if(flag=='A')
{
scanf("%lld",&x);
update(1,a,b,x);
}
else if(flag=='S')
printf("%lld\n",query(1,a,b,true));
else if(flag == 'Q')
printf("%lld\n",query(1,a,b,false));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: