1798: [Ahoi2009]Seq 维护序列seq

Description

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

Input

第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

Output

对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

Sample Input

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

Sample Output

2
35
8

HINT

【样例说明】

初始时数列为(1,2,3,4,5,6,7)。
经过第1次操作后,数列为(1,10,15,20,25,6,7)。
对第2次操作,和为10+15+20=45,模43的结果是2。
经过第3次操作后,数列为(1,10,24,29,34,15,16}
对第4次操作,和为1+10+24=35,模43的结果是35。
对第5次操作,和为29+34+15+16=94,模43的结果是8。



测试数据规模如下表所示

数据编号 1 2 3 4 5 6 7 8 9 10
N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000
M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

 
 
 
在zyf大神的帮助下艰难的A掉了。。。需要注意的地方一是要进行两个lazy标记,添加*的运算时还要用这个数乘要加的lazy标记,
二是pushdown到儿子的时候也要先乘再加;三是答案要%,而且要求一次答案%一次,lazy标记也要%(因为这个一直wa)。。。。。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #define MAX 100010
  7 using namespace std;
  8 long long a[MAX],k;
  9 struct tree{
 10     long long l,r,sum,lazy,lazy2;
 11 }f[MAX*4];
 12 
 13 void pushup(int i){
 14     f[i].sum=(f[i*2+1].sum+f[i*2].sum)%k;
 15 }
 16 
 17 void update(int i,long long x,long long y)
 18 {
 19 
 20     f[i].sum*=y;
 21     f[i].sum%=k;
 22     f[i].sum+=x*(f[i].r-f[i].l+1);
 23     f[i].sum%=k;
 24     f[i].lazy*=y;
 25     f[i].lazy%=k;
 26     f[i].lazy+=x;
 27     f[i].lazy%=k;
 28     f[i].lazy2*=y;
 29     f[i].lazy2%=k;
 30     return;
 31 }
 32 
 33 void pushdown(int i){
 34     if(f[i].lazy!=0||f[i].lazy2!=1){
 35         update(i*2,f[i].lazy,f[i].lazy2);
 36         update(i*2+1,f[i].lazy,f[i].lazy2);
 37         f[i].lazy=0;
 38         f[i].lazy2=1;
 39         return;
 40     }
 41     else return;
 42 }
 43 
 44 void build(int i,int left,int right){
 45     int mid=(left+right)/2;
 46     f[i].lazy=0;f[i].lazy2=1;
 47     f[i].l=left;f[i].r=right;
 48     if(left==right){
 49         f[i].sum=a[left]%k;
 50         return;
 51     }
 52     build(i*2,left,mid);
 53     build(i*2+1,mid+1,right);
 54     pushup(i);
 55 }
 56 
 57 void addmeg(int i,int left,int right,long long v){
 58     int mid=(f[i].l+f[i].r)/2;
 59     if(f[i].l==left&&f[i].r==right){
 60         update(i,v,1);
 61         return;
 62     }
 63     pushdown(i);
 64     if(mid>=right)addmeg(i*2,left,right,v);    
 65     else if(mid<left)addmeg(i*2+1,left,right,v);
 66     else addmeg(i*2,left,mid,v),addmeg(i*2+1,mid+1,right,v);
 67     pushup(i);
 68 }
 69 
 70 void multmeg(int i,int left,int right,long long v){
 71     int mid=(f[i].l+f[i].r)/2;
 72     if(f[i].l==left&&f[i].r==right){
 73         update(i,0,v);
 74         return;
 75     }
 76     pushdown(i);
 77     if(mid>=right)multmeg(i*2,left,right,v);    
 78     else if(mid<left)multmeg(i*2+1,left,right,v);
 79     else multmeg(i*2,left,mid,v),multmeg(i*2+1,mid+1,right,v);
 80     pushup(i);
 81 }
 82 
 83 long long query(int i,int left,int right) {
 84 
 85         int mid=(f[i].l+f[i].r)/2;
 86         
 87         if(f[i].l==left&&f[i].r==right) return f[i].sum;
 88         pushdown(i);
 89         if(mid>=right) return query(i*2,left,right);
 90         if(mid<left) return query(i*2+1,left,right);
 91         return (query(i*2,left,mid)+query(i*2+1,mid+1,right))%k;
 92     
 93 }
 94 
 95 int main(){
 96     int n;
 97     scanf("%d%d",&n,&k);
 98     for(int i=1;i<=n;i++)
 99     scanf("%lld",&a[i]);
100     build(1,1,n);
101     scanf("%lld",&n);
102     for(int i=1;i<=n;i++){
103         int x,y,z;
104         long long r;
105         scanf("%d",&x);
106         if(x==1){
107             scanf("%d%d%lld",&y,&z,&r);
108             multmeg(1,y,z,r);
109         }
110         if(x==2){
111             scanf("%d%d%lld",&y,&z,&r);
112             addmeg(1,y,z,r);
113         }
114         if(x==3){
115             scanf("%d%d",&y,&z);
116             printf("%lld\n",query(1,y,z)%k);
117         }
118     }
119     return 0;
120 }
View Code

似乎对于%有更好的写法。。。但是蒟蒻表示自己并不会。。TAT。。。

posted @ 2015-09-18 09:02  HTWX  阅读(122)  评论(0编辑  收藏  举报