首页 > 代码库 > [CodeVS4919]线段树练习4

[CodeVS4919]线段树练习4

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

 1 #include<iostream> 2 #include<algorithm> 3 #define maxn 100001 4 #define root 1 5 #define _left <<1 6 #define _right <<1|1 7 int n; 8 class SegmentTree { 9     private:10         int val[maxn<<2][7],lazy[maxn<<2];11         void push_up(const int p) {12             for(int i=0;i<7;i++) {13                 val[p][i]=val[p _left][i]+val[p _right][i];14             }15         }16         void swap(const int p,const int q) {17             if(!lazy[p]) return;18             int t[7];19             for(int i=0;i<7;i++) t[(i+q)%7]=val[p][i];20             for(int i=0;i<7;i++) val[p][i]=t[i];21         }22         void push_down(const int p) {23             if(!lazy[p]) return;24             lazy[p _left]=lazy[p _left]+lazy[p];25             lazy[p _right]=lazy[p _right]+lazy[p];26             swap(p _left,lazy[p]);27             swap(p _right,lazy[p]);28             lazy[p]=0;29         }30     public:31         void build(const int p,const int b,const int e) {32             lazy[p]=0;33             if(b==e) {34                 int x;35                 std::cin>>x;36                 val[p][x%7]=1;37                 return;38             }39             int mid=(b+e)>>1;40             build(p _left,b,mid);41             build(p _right,mid+1,e);42             push_up(p);43         }44         void modify(const int p,const int b,const int e,const int l,const int r,const int x) {45             if(b!=e) push_down(p);46             if((b==l)&&(e==r)) {47                 lazy[p]=lazy[p]+x;48                 swap(p,x);49                 return;50             }51             int mid=(b+e)>>1;52             if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x);53             if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x);54             push_up(p);55         }56         int query(const int p,const int b,const int e,const int l,const int r) {57             if(b!=e) push_down(p);58             if((b==l)&&(e==r)) {59                 return val[p][0];60             }61             int mid=(b+e)>>1,ans=0;62             if(l<=mid) ans+=query(p _left,b,mid,l,std::min(mid,r));63             if(r>mid) ans+=query(p _right,mid+1,e,std::max(mid+1,l),r);64             return ans;65         }66 };67 SegmentTree tree;68 int main() {69     std::ios_base::sync_with_stdio(false);70     std::cin>>n;71     tree.build(root,1,n);72     int q;73     for(std::cin>>q;q--;) {74         char op[6];75         std::cin>>op;76         if(op[0]==a) {77             int x,y,k;78             std::cin>>x>>y>>k;79             tree.modify(root,1,n,x,y,k);80         }81         else {82             int x,y;83             std::cin>>x>>y;84             std::cout<<tree.query(root,1,n,x,y)<<std::endl;85         }86     }87     return 0;88 }

 

[CodeVS4919]线段树练习4