补个线段树

Posted ChenThree

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了补个线段树相关的知识,希望对你有一定的参考价值。

技术分享图片
  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<cmath>
  4 #include<ctime>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<set>
  9 #define inf (0x7fffffff)
 10 #define l(a) ((a)<<1)
 11 #define r(a) ((a)<<1|1)
 12 #define b(a) (1<<(a))
 13 #define rep(i,a,b) for(int i=a;i<=(b);i++)
 14 #define clr(a) memset(a,0,sizeof(a))
 15 typedef long long ll;
 16 typedef unsigned long long ull;
 17 using namespace std;
 18 int readint(){
 19     int t=0,f=1;char c=getchar();
 20     while(!isdigit(c)){
 21         if(c==-) f=-1;
 22         c=getchar();
 23     }
 24     while(isdigit(c)){
 25         t=(t<<3)+(t<<1)+c-0;
 26         c=getchar();
 27     }
 28     return t*f;
 29 }
 30 const int maxn=100009;
 31 struct node{
 32     int l,r;
 33     ll s,a,m;
 34 }x[maxn<<2];
 35 int n,m;
 36 ll mod;
 37 void maintain(int t){
 38     x[t].s=(x[l(t)].s+x[r(t)].s)%mod;
 39 }
 40 void pushdown(int t){
 41     if(x[t].l==x[t].r){
 42         x[t].a=0;x[t].m=1;return;
 43     }
 44     if(x[t].m!=1){
 45         x[l(t)].s=x[l(t)].s*x[t].m%mod;
 46         x[r(t)].s=x[r(t)].s*x[t].m%mod;
 47         x[l(t)].m=x[l(t)].m*x[t].m%mod;x[r(t)].m=x[r(t)].m*x[t].m%mod;
 48         x[l(t)].a=x[l(t)].a*x[t].m%mod;x[r(t)].a=x[r(t)].a*x[t].m%mod;
 49         x[t].m=1;
 50     }
 51     if(x[t].a){
 52         x[l(t)].s=(x[l(t)].s+(x[l(t)].r-x[l(t)].l+1)*x[t].a)%mod;
 53         x[r(t)].s=(x[r(t)].s+(x[r(t)].r-x[r(t)].l+1)*x[t].a)%mod;
 54         x[l(t)].a=(x[l(t)].a+x[t].a)%mod;x[r(t)].a=(x[r(t)].a+x[t].a)%mod;
 55         x[t].a=0;
 56     }    
 57 }
 58 ll del;
 59 void add(int t,int l,int r){
 60     pushdown(t);
 61     if(x[t].l==l&&x[t].r==r){
 62         x[t].s=(x[t].s+(x[t].r-x[t].l+1)*del)%mod;
 63         x[t].a=(x[t].a+del)%mod;
 64         return;
 65     }
 66     int mid=(x[t].l+x[t].r)>>1;
 67     if(l>mid) add(r(t),l,r);
 68     else if(r<=mid) add(l(t),l,r);
 69     else{
 70         add(l(t),l,mid);
 71         add(r(t),mid+1,r);
 72     }
 73     maintain(t);
 74 }
 75 void mul(int t,int l,int r){
 76     pushdown(t);
 77     if(x[t].l==l&&x[t].r==r){
 78         x[t].s=(x[t].s*del)%mod;
 79         x[t].m=x[t].m*del%mod;
 80         x[t].a=x[t].a*del%mod;
 81         return;
 82     }
 83     int mid=(x[t].l+x[t].r)>>1;
 84     if(l>mid) mul(r(t),l,r);
 85     else if(r<=mid) mul(l(t),l,r);
 86     else{
 87         mul(l(t),l,mid);
 88         mul(r(t),mid+1,r);
 89     }
 90     maintain(t);
 91 }
 92 ll qury(int t,int l,int r){
 93     pushdown(t);
 94     if(x[t].l==l&&x[t].r==r) return x[t].s;
 95     int mid=(x[t].l+x[t].r)>>1;
 96     if(l>mid) return qury(r(t),l,r)%mod;
 97     if(r<=mid) return qury(l(t),l,r)%mod;
 98     return (qury(l(t),l,mid)%mod+qury(r(t),mid+1,r)%mod)%mod;
 99 }
100 void build(int t,int l,int r){
101     x[t].l=l;x[t].r=r;x[t].m=1;
102     if(l==r){
103         x[t].s=readint()%mod;
104         return;
105     }
106     int mid=(l+r)>>1;
107     build(l(t),l,mid);
108     build(r(t),mid+1,r);
109     maintain(t);
110 }
111 int main(){
112     //freopen("#input.txt","r",stdin);
113     //freopen("#output.txt","w",stdout);
114     n=readint();m=readint();mod=readint();
115     build(1,1,n);
116     while(m--){
117         int opt=readint(),L=readint(),R=readint();
118         if(opt==3) printf("%lld\n",(qury(1,L,R)+mod)%mod);
119         else{
120             del=readint()%mod;
121             if(opt==2) add(1,L,R);
122             else mul(1,L,R);
123         }
124     }
125     //fclose(stdin);
126     //fclose(stdout);
127     return 0;
128 }
View Code

 

以上是关于补个线段树的主要内容,如果未能解决你的问题,请参考以下文章

线段树-代码实现细节与技巧

线段树

CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

线段树合并

数据结构——线段树

论线段树:二