您的位置:首页 > 其它

[CodeVS4919]线段树练习4

2017-05-21 15:27 288 查看

线段树。每个节点分别维护当前区间内%7分别等于0~6的数的个数,lazy tag记录当前区间增加的量,查询时将val“平移”lazy个即可。

#include<iostream>
#include<algorithm>
#define maxn 100001
#define root 1
#define _left <<1
#define _right <<1|1
int n;
class SegmentTree {
private:
int val[maxn<<2][7],lazy[maxn<<2];
void push_up(const int p) {
for(int i=0;i<7;i++) {
val

[i]=val[p _left][i]+val[p _right][i]; } } void swap(const int p,const int q) { if(!lazy[p]) return; int t[7]; for(int i=0;i<7;i++) t[(i+q)%7]=val[p][i]; for(int i=0;i<7;i++) val[p][i]=t[i]; } void push_down(const int p) { if(!lazy[p]) return; lazy[p _left]=lazy[p _left]+lazy[p]; lazy[p _right]=lazy[p _right]+lazy[p]; swap(p _left,lazy[p]); swap(p _right,lazy[p]); lazy[p]=0; } public: void build(const int p,const int b,const int e) { lazy[p]=0; if(b==e) { int x; std::cin>>x; val[p][x%7]=1; return; } int mid=(b+e)>>1; build(p _left,b,mid); build(p _right,mid+1,e); push_up(p); } void modify(const int p,const int b,const int e,const int l,const int r,const int x) { if(b!=e) push_down(p); if((b==l)&&(e==r)) { lazy[p]=lazy[p]+x; swap(p,x); return; } int mid=(b+e)>>1; if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x); if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x); push_up(p); } int query(const int p,const int b,const int e,const int l,const int r) { if(b!=e) push_down(p); if((b==l)&&(e==r)) { return val[p][0]; } int mid=(b+e)>>1,ans=0; if(l<=mid) ans+=query(p _left,b,mid,l,std::min(mid,r)); if(r>mid) ans+=query(p _right,mid+1,e,std::max(mid+1,l),r); return ans; } }; SegmentTree tree; int main() { std::ios_base::sync_with_stdio(false); std::cin>>n; tree.build(root,1,n); int q; for(std::cin>>q;q--;) { char op[6]; std::cin>>op; if(op[0]=='a') { int x,y,k; std::cin>>x>>y>>k; tree.modify(root,1,n,x,y,k); } else { int x,y; std::cin>>x>>y; std::cout<<tree.query(root,1,n,x,y)<<std::endl; } } return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: