bzoj 3323: [Scoi2013]多项式的运算.
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3323: [Scoi2013]多项式的运算.相关的知识,希望对你有一定的参考价值。
3323: [Scoi2013]多项式的运算
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 412 Solved: 148
[Submit][Status][Discuss]
Description
某天,mzry1992 一边思考着一个项目问题一边在高速公路上骑着摩托车。一个光头踢了他一脚,摩托车损坏,而他也被送进校医院打吊针。现在该项目的截止日期将近,他不得不请你来帮助他完成这个项目。该项目的目的是维护一个动态的关于x 的无穷多项式F(x) = a0 * x^0 + a1 * x^1 + a2 * x^2 + ... ,这个多项式初始时对于所有i有ai = 0。
操作者可以进行四种操作:
1. 将x^L 到x^R 这些项的系数乘上某个定值v
2. 将x^L 到x^R 这些项的系数加上某个定值v
3. 将x^L 到x^R 这些项乘上x变量
4. 将某个定值v代入多项式F(x),并输出代入后多项式的值,之后多项式还原为代入前的状况
经过观察,项目组发现使用者的操作集中在前三种,第四种操作不会出现超过10次。mzry1992 负责这个项目的核心代码,你能帮他实现么。
Input
输入的第一行有一个整数n 代表操作的个数。
接下来n 行,每行一个操作,格式如下:
mul L R v 代表第一种操作
add L R v 代表第二种操作
mulx L R 代表第三种操作
query v 代表第四种操作
对于30% 的数据:N <= 5000,0 <= L <= R <= 5000,0 <= v <= 10^9
另有20% 的数据:N <= 10^5,0 <= L <= R <= 10^5,0 <= v <= 10^9,没有mulx 操作
剩下的50% 的数据:N <= 10^5,0 <= L <= R <= 10^5,0 <= v <= 10^9
接下来n 行,每行一个操作,格式如下:
mul L R v 代表第一种操作
add L R v 代表第二种操作
mulx L R 代表第三种操作
query v 代表第四种操作
对于30% 的数据:N <= 5000,0 <= L <= R <= 5000,0 <= v <= 10^9
另有20% 的数据:N <= 10^5,0 <= L <= R <= 10^5,0 <= v <= 10^9,没有mulx 操作
剩下的50% 的数据:N <= 10^5,0 <= L <= R <= 10^5,0 <= v <= 10^9
Output
对于每个query 操作,输出对应的答案,结果可能较大,需要模上20130426。
Sample Input
6
add 0 1 7
query 1
mul 0 1 7
query 2
mulx 0 1
query 3
Sample Output
14
147
588
HINT
操作一之后,多项式为F(x) = 7x + 7。
操作三之后,多项式为F(x) = 49x + 49。
操作五之后,多项式为F(x) = 49x^2 + 49x。
应上传者要求,此系列试题不公开,如有异议,本站将删除之。
#include<cstdio> #include<cstring> using namespace std; typedef long long ll; #define maxn 100010 #define mod 20130426ll int ch[maxn][2],fa[maxn]; int size[maxn],n,root; ll a[maxn],add[maxn]; ll mul[maxn],mi,ans; inline int input() { int x=0,a=1;char c=getchar(); for(;c<‘0‘||c>‘9‘;c=getchar()) if(c==‘-‘) a=-1; for(;c>=‘0‘&&c<=‘9‘;c=getchar()) x=x*10+c-‘0‘; return x*a; } inline void updata(int x) { int lc=ch[x][0],rc=ch[x][1]; size[x]=size[lc]+size[rc]+1; return; } inline void pushdown(int x) { int lc=ch[x][0],rc=ch[x][1]; ll &Mul=mul[x],&Add=add[x]; a[x]=(a[x]*Mul)%mod; a[x]=(a[x]+Add)%mod; add[lc]=(add[lc]*Mul+Add)%mod; add[rc]=(add[rc]*Mul+Add)%mod; mul[lc]=(mul[lc]*Mul)%mod; mul[rc]=(mul[rc]*Mul)%mod; Mul=1ll,Add=0ll; return; } inline int son(int x) { return ch[fa[x]][1]==x; } void rotate(int x) { int y=fa[x],z=fa[y]; int b=son(x),c=son(y),a=ch[x][!b]; if(z) ch[z][c]=x; else root=x; fa[x]=z; if(a) fa[a]=y; ch[y][b]=a; ch[x][!b]=y; fa[y]=x; updata(y); updata(x); return; } void splay(int x,int i) { while(fa[x]!=i) { int y=fa[x],z=fa[y]; if(z==i) { pushdown(y); pushdown(x); rotate(x); } else { pushdown(z); pushdown(y); pushdown(x); if(son(x)==son(y)) { rotate(y); rotate(x); } else { rotate(x); rotate(x); } } } return; } int getkth(int x,int k) { int lc=ch[x][0]; if(size[lc]+1==k) return x; if(size[lc]>=k) return getkth(lc,k); return getkth(ch[x][1],k-size[lc]-1); } void plus(int L,int R,int v) { int l=getkth(root,L); int r=getkth(root,R+2); splay(l,0); splay(r,l); int x=ch[r][0]; add[x]=(add[x]+v)%mod; return; } void multiply(int L,int R,int v) { int l=getkth(root,L); int r=getkth(root,R+2); splay(l,0); splay(r,l); int x=ch[r][0]; add[x]=(add[x]*v)%mod; mul[x]=(mul[x]*v)%mod; return; } void multiply_plus(int L,int R) { int rm=getkth(root,R); int r1=getkth(root,R+1); int r2=getkth(root,R+2); splay(rm,0); splay(r2,rm); pushdown(rm); pushdown(r2); pushdown(r1); a[r2]=(a[r2]+a[r1])%mod; ch[r2][0]=0; size[r2]--; size[rm]--; int lm=getkth(root,L); int l=getkth(root,L+1); splay(lm,0); splay(l,lm); pushdown(lm); pushdown(l); ch[l][0]=r1; fa[r1]=l; size[r1]=1; size[l]++; size[lm]++; a[r1]=0; add[r1]=0; mul[r1]=1; return; } void dfs(int x,ll v) { pushdown(x); int lc=ch[x][0],rc=ch[x][1]; if(lc) dfs(lc,v); if(mi==-1) mi=1; else { ans=(ans+a[x]*mi)%mod; mi=(mi*v)%mod; } if(rc) dfs(rc,v); return; } void query(ll v) { ans=0,mi=-1; dfs(root,v); printf("%lld\n",ans); return; } void init(int n) { n+=5; root=1; for(int i=1;i<n;i++) ch[i][1]=i+1; for(int i=2;i<=n;i++) fa[i]=i-1; for(int i=n;i>=1;i--) { updata(i); mul[i]=1ll; } return; } int main() { n=input(); for(init(n);n>=1;n--) { char op[10]; scanf("%s",op); int x=input(),len=strlen(op); if(op[0]==‘m‘) { int y=input(); if(len==3) { int z=input(); multiply(x+1,y+1,z); } else multiply_plus(x+1,y+1); } else if(op[0]==‘a‘) { int y=input(),z=input(); plus(x+1,y+1,z); } else query((ll)x); } return 0; }
以上是关于bzoj 3323: [Scoi2013]多项式的运算.的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ3325 [Scoi2013]密码 manacher
bzoj3325[Scoi2013]密码 逆模拟Manacher