前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >P2023 [AHOI2009]维护序列

P2023 [AHOI2009]维护序列

作者头像
attack
发布2018-04-13 11:00:43
7060
发布2018-04-13 11:00:43
举报

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

输入输出格式

输入格式:

第一行两个整数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)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

输出格式:

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

输入输出样例

输入样例#1:

代码语言:javascript
复制
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

输出样例#1:

代码语言:javascript
复制
2
35
8

说明

【样例说明】

初始时数列为(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

Source: Ahoi 2009

调了一个半小时,调不出来

不调了、、

代码语言:javascript
复制
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define lli long long 
  7 using namespace std;
  8 const int MAXN=500001;
  9 lli n,m,mod,ans;
 10 void read(lli & n)
 11 {
 12     char c='+';lli x=0;bool flag=0;
 13     while(c<'0'||c>'9')
 14     {c=getchar();if(c=='-')flag=1;}
 15     while(c>='0'&&c<='9')
 16     {x=x*10+(c-48),c=getchar();}
 17     flag==1?n=-x:n=x;
 18 }
 19 struct node
 20 {
 21     lli l,r,w,k,fc,fj;
 22 }tree[MAXN*4];
 23 void pushdown(lli k,lli ll,lli rr,lli mid)
 24 {
 25     tree[k<<1].w*=tree[k].fc%mod;
 26     tree[k<<1|1].w*=tree[k].fc%mod;
 27     tree[k<<1].w=(tree[k<<1].w+tree[k].fj*(mid-ll+1))%mod;
 28     tree[k<<1|1].w=(tree[k<<1|1].w+tree[k].fj*(rr-mid))%mod;
 29     
 30     tree[k<<1].fc%=mod;tree[k<<1|1].fc%=mod;
 31     tree[k<<1].fj%=mod;tree[k<<1|1].fj%=mod;
 32     tree[k<<1].w%=mod;tree[k<<1|1].w%=mod;
 33     
 34     tree[k<<1].fc*=tree[k].fc%mod;tree[k<<1|1].fc*=tree[k].fc%mod;
 35     tree[k<<1].fj*=tree[k].fc%mod;tree[k<<1|1].fj*=tree[k].fc%mod;
 36     tree[k<<1].fj=(tree[k<<1].fj+tree[k].fj)%mod;
 37     tree[k<<1|1].fj=(tree[k<<1|1].fj+tree[k].fj)%mod;
 38     
 39     
 40     tree[k].fc=1;
 41     tree[k].fj=0;
 42     
 43     
 44     tree[k<<1].fc%=mod;tree[k<<1|1].fc%=mod;
 45     tree[k<<1].fj%=mod;tree[k<<1|1].fj%=mod;
 46     tree[k<<1].w%=mod;tree[k<<1|1].w%=mod;
 47 }
 48 void update(lli k)
 49 {
 50     tree[k].w=(tree[k<<1].w+tree[k<<1|1].w)%mod;
 51 }
 52 void build_tree(lli ll,lli rr,lli k)
 53 {
 54     tree[k].l=ll;tree[k].r=rr;tree[k].k=k;
 55     tree[k].fc=1;tree[k].fj=0;
 56     if(tree[k].l==tree[k].r)
 57     {
 58         read(tree[k].w);
 59         tree[k].w%=mod;
 60         return ;
 61     }
 62     lli mid=(ll+rr)>>1;
 63     build_tree(ll,mid,k<<1);
 64     build_tree(mid+1,rr,k<<1|1);
 65     update(k);
 66 }
 67 void interval_mul(lli k,lli ll,lli rr,lli v)
 68 {
 69     if(ll>tree[k].r||rr<tree[k].l)
 70     return ;
 71     if(tree[k].l>=ll&&tree[k].r<=rr)
 72     {
 73         tree[k].w*=v%mod;
 74         tree[k].fc*=v%mod;
 75         tree[k].fj*=v%mod;
 76         return ;
 77     }
 78     lli mid=(tree[k].l+tree[k].r)>>1;
 79     pushdown(k,tree[k].l,tree[k].r,mid);
 80     if(ll<=mid)
 81         interval_mul(k<<1,ll,rr,v);
 82     if(rr>mid)
 83         interval_mul(k<<1|1,ll,rr,v);
 84     update(k);
 85 }
 86 void interval_add(lli k,lli ll,lli rr,lli v)
 87 {
 88     if(ll>tree[k].r||rr<tree[k].l)
 89     return ;
 90     if(tree[k].l>=ll&&tree[k].r<=rr)
 91     {
 92         tree[k].w=(tree[k].w+v*(tree[k].r-tree[k].l+1))%mod;
 93         //tree[k].fc*=v%mod;
 94         tree[k].fj=(tree[k].fj+v)%mod;
 95         return ;
 96     }
 97     lli mid=(tree[k].l+tree[k].r)>>1;
 98     pushdown(k,tree[k].l,tree[k].r,mid);
 99     if(ll<=mid)
100         interval_add(k<<1,ll,rr,v);
101     if(rr>mid)
102         interval_add(k<<1|1,ll,rr,v);
103     update(k);
104 
105 }
106 void interval_ask(lli k,lli ll,lli rr)
107 {
108     if(ll>tree[k].r||rr<tree[k].l)
109     return ;
110     if(tree[k].l>=ll&&tree[k].r<=rr)
111     {
112         ans=(ans+tree[k].w)%mod;
113         return ;
114     }
115     lli mid=(tree[k].l+tree[k].r)>>1;
116     pushdown(k,tree[k].l,tree[k].r,mid);
117     if(ll<=mid)
118         interval_ask(k<<1,ll,rr);
119     if(rr>mid)
120         interval_ask(k<<1|1,ll,rr);
121     update(k);
122 }
123 int main()
124 {
125     read(n);read(mod);
126     build_tree(1,n,1);
127     read(m);
128     for(lli i=1;i<=m;i++)
129     {
130         lli how,x,y,c;
131         read(how);
132         if(how==1)
133         {
134             read(x);read(y);read(c);
135             interval_mul(1,x,y,c%mod);//乘 
136         }
137         else if(how==2)
138         {
139             read(x);read(y);read(c);
140             interval_add(1,x,y,c%mod);// 加 
141         }
142         else if(how==3)
143         {
144             ans=0;
145             read(x);read(y);
146             interval_ask(1,x,y);
147             printf("%lld\n",ans);
148         }
149     }
150     return 0;
151 }
代码语言:javascript
复制
 1 #include<iostream>
 2 #include<cstdio>
 3 #define lli long long int 
 4 #define re register
 5 #define LL long long
 6 #define M 500000
 7 using namespace std;
 8 void read(lli & n)
 9 {
10     char c='+';lli x=0;bool flag=0;
11     while(c<'0'||c>'9')
12     {c=getchar();if(c=='-')flag=1;}
13     while(c>='0'&&c<='9')
14     {x=x*10+(c-48),c=getchar();}
15     flag==1?n=-x:n=x;
16 }
17 LL mogician,a[M/2+1];
18 int n;
19 struct Tree{
20     LL sum,add,mult;
21 }tr[M+1];
22 inline void build(int k,int l,int r){
23     tr[k].mult=1;
24     if(l==r){
25         tr[k].sum=a[l];
26         return ;
27     }
28     int mid=(l+r)>>1;
29     build(k<<1,l,mid);
30     build(k<<1|1,mid+1,r);
31     tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%mogician;
32 }
33 inline void Work_Out(int k,int l,int r,LL mu,LL ad){
34     tr[k].add=(tr[k].add*mu+ad)%mogician;
35     tr[k].mult=(tr[k].mult*mu)%mogician;
36     tr[k].sum=(tr[k].sum*mu+(r-l+1)*ad)%mogician;
37 }
38 inline void Push_Down(int k,int l,int r){
39     if(tr[k].add==0&&tr[k].mult==1)
40         return ;
41     int mid=(l+r)>>1;
42     Work_Out(k<<1,l,mid,tr[k].mult,tr[k].add);
43     Work_Out(k<<1|1,mid+1,r,tr[k].mult,tr[k].add);
44     tr[k].add=0;
45     tr[k].mult=1;
46 }
47 inline void Lazy_Tag(int k,int l,int r,int x,int y,LL mu,LL ad){
48     if(x<=l&&r<=y){
49         Work_Out(k,l,r,mu,ad);
50         return ;
51     }
52     Push_Down(k,l,r);
53     int mid=(l+r)>>1;
54     if(x<=mid)
55         Lazy_Tag(k<<1,l,mid,x,y,mu,ad);
56     if(mid<y)
57         Lazy_Tag(k<<1|1,mid+1,r,x,y,mu,ad);
58     tr[k].sum=(tr[k<<1].sum+tr[k<<1|1].sum)%mogician;
59 }
60 inline LL Q(int k,int l,int r,int x,int y){
61     if(x<=l&&r<=y)
62         return tr[k].sum%mogician;
63     Push_Down(k,l,r);
64     int mid=(l+r)>>1;
65     return    ((x<=mid?Q(k<<1,l,mid,x,y)%mogician:0)+(mid<y?Q(k<<1|1,mid+1,r,x,y)%mogician:0))%mogician;
66 }
67 int m,d,x,y;
68 LL k;
69 int main(){
70     
71     scanf("%lld%lld",&n,&mogician);
72     for(re int i=1;i<=n;i++){
73         scanf("%lld",&a[i]);
74         a[i]%=mogician;
75     }
76     build(1,1,n);
77     scanf("%d",&m);
78     for(re int i=1;i<=m;i++){
79         scanf("%d%d%d",&d,&x,&y);
80         if(d==3)
81             printf("%lld\n",Q(1,1,n,x,y));
82         else{
83             scanf("%lld",&k);
84             k%=mogician;
85             d==1?Lazy_Tag(1,1,n,x,y,k,0):Lazy_Tag(1,1,n,x,y,1,k);
86         }
87     }
88     return 0;
89 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-06-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 输入输出格式
  • 输入输出样例
  • 说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档