[BZOJ1798][AHOI2009]Seq维护序列 线段树

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798

一眼看过去线段树,事实上就是线段树。对于乘和加的两个标记,我们可以规定一个顺序,比如先乘后加。每次乘的时候利用乘法分配律就可以分别更新标记,而加就直接加上去就好了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 typedef long long ll;
  6 int inline readint(){
  7     int Num;char ch;
  8     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
  9     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
 10     return Num;
 11 }
 12 void outint(int x){
 13     if(x>=10) outint(x/10);
 14     putchar(x%10+'0');
 15 }
 16 int N,M,P;
 17 int sum[(100000<<2)+10],col1[(100000<<2)+10],col2[(100000<<2)+10];
 18 #define lson l,mid,rt<<1
 19 #define rson mid+1,r,rt<<1|1
 20 void Pushup(int &rt){
 21     sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%P;
 22 }
 23 void Build(int l,int r,int rt){
 24     col1[rt]=1;
 25     if(l==r){
 26         sum[rt]=readint()%P;
 27         return;
 28     }
 29     int mid=l+r>>1;
 30     if(l<=mid) Build(lson);
 31     if(r>mid) Build(rson);
 32     Pushup(rt);
 33 }
 34 void Pushdown(int &rt,int &l,int &r){
 35     if(col1[rt]!=1){
 36         col1[rt<<1]=(ll)col1[rt<<1]*col1[rt]%P;
 37         col2[rt<<1]=(ll)col2[rt<<1]*col1[rt]%P;
 38         sum[rt<<1]=(ll)sum[rt<<1]*col1[rt]%P;
 39         col1[rt<<1|1]=(ll)col1[rt<<1|1]*col1[rt]%P;
 40         col2[rt<<1|1]=(ll)col2[rt<<1|1]*col1[rt]%P;
 41         sum[rt<<1|1]=(ll)sum[rt<<1|1]*col1[rt]%P;
 42         col1[rt]=1;
 43     }
 44     if(col2[rt]){
 45         col2[rt<<1]=(col2[rt<<1]+col2[rt])%P;
 46         sum[rt<<1]=((ll)col2[rt]*((l+r>>1)-l+1)%P+sum[rt<<1])%P;
 47         col2[rt<<1|1]=(col2[rt<<1|1]+col2[rt])%P;
 48         sum[rt<<1|1]=((ll)col2[rt]*(r-(l+r>>1))%P+sum[rt<<1|1])%P;
 49         col2[rt]=0;
 50     }
 51 }
 52 void Mul(int l,int r,int rt,int L,int R,int x){
 53     if(l>=L&&r<=R){
 54         col1[rt]=(ll)col1[rt]*x%P;
 55         col2[rt]=(ll)col2[rt]*x%P;
 56         sum[rt]=(ll)sum[rt]*x%P;
 57         return;
 58     }
 59     Pushdown(rt,l,r);
 60     int mid=l+r>>1;
 61     if(L<=mid) Mul(lson,L,R,x);
 62     if(R>mid) Mul(rson,L,R,x);
 63     Pushup(rt);
 64 }
 65 void Add(int l,int r,int rt,int L,int R,int x){
 66     if(l>=L&&r<=R){
 67         col2[rt]=(col2[rt]+x)%P;
 68         sum[rt]=((ll)(r-l+1)*x%P+sum[rt])%P;
 69         return;
 70     }
 71     Pushdown(rt,l,r);
 72     int mid=l+r>>1;
 73     if(L<=mid) Add(lson,L,R,x);
 74     if(R>mid) Add(rson,L,R,x);
 75     Pushup(rt);
 76 }
 77 int Qry(int l,int r,int rt,int L,int R){
 78     if(l>=L&&r<=R) return sum[rt];
 79     Pushdown(rt,l,r);
 80     int mid=l+r>>1,ret=0;
 81     if(L<=mid) ret=Qry(lson,L,R);
 82     if(R>mid) ret=(ret+Qry(rson,L,R))%P;
 83     return ret;
 84 }
 85 int main(){
 86     N=readint();
 87     P=readint();
 88     Build(1,N,1);
 89     M=readint();
 90     for(int i=1;i<=M;i++){
 91         int opt=readint(),t,g,c;
 92         switch(opt){
 93             case 1:
 94                 t=readint();
 95                 g=readint();
 96                 c=readint()%P;
 97                 Mul(1,N,1,t,g,c);
 98                 break;
 99             case 2:
100                 t=readint();
101                 g=readint();
102                 c=readint()%P;
103                 Add(1,N,1,t,g,c);
104                 break;
105             case 3:
106                 t=readint();
107                 g=readint();
108                 outint(Qry(1,N,1,t,g));
109                 putchar('\n');
110                 break;
111         }
112     }
113     return 0;
114 }

 

posted @ 2017-09-27 21:02  halfrot  阅读(128)  评论(0编辑  收藏  举报