BZOJ3323 SCOI2013 多项式的运算

AC链接:传送门

题目分析:

  一道比较难写的splay模板题,可以看出scoi与hnoi相比,思维难度略低。

  首先观察操作4,题目限制操作4的个数不会超过10个,但是经过分析可以发现题目中的无穷多项式是唬人的,最多的一项只会到达2*105级别,那么每一次用O(n)可以计算,最多十次仅O(10n),因此这一部分可以暴力解决。

  忽略操作3,那么把多项式的每一项看作splay上的第i个点,预先建好n个点会使问题变简单许多,加法和乘法可以用标记解决,那么在没有操作3的情况下有一个O(nlogn)的splay做法。

  加入操作3,操作3在[l,r]上乘以x,仅仅只会平移一项,那么我们将这一步拆分成下面独立的几步:

    1.找到第l项,第r项与第r+1项所对应的结点的值。

    2.将第r+1项所对应的结点的data加上第r项所对应的结点的data。

    3.旋转,提取区间[l,r]。

    4.删除第r项对应的结点。

    5.给区间[l,r]对应的结点打上项数+1的标记,这时候我们发现,它们在splay中的相对位置没有改变!因此这个做法是成立的。

    6.补充第l项对应的结点,用删除的结点补充即可。

题目难点:

  这道题的难点在于代码的难写程度。维护三个标记是其一大恶心之处,但是其中的项+1标记与另外两个标记是独立的。

  另外两个标记的维护与洛谷的某道线段树练习相似。

  我们先让有乘法标记时乘法优于加法处理,那么当每个乘法标记被打上的时候,我们需要下放结点上的加法标记。但是打加法标记时不需要下放乘法标记,这样标记下传是O(1)的。

  

代码如下:

  

  1 #include<bits/stdc++.h>
  2 #define L (t[now].ch[0])
  3 #define R (t[now].ch[1])
  4 using namespace std;
  5 
  6 typedef long long ll;
  7 
  8 const ll maxn = 300010;
  9 const ll mod = 20130426;
 10 struct node{
 11     ll data;
 12     ll num,ch[2],fa;
 13     ll lznum,lzmul,lzad;
 14     node(){lzmul=1;data=num=ch[0]=ch[1]=fa=lznum=lzad=0;}
 15 }t[maxn];
 16 ll n,root=1,nb=1;
 17 
 18 void r0(ll now,ll dr){ // 0 left ,1 right
 19     ll son = t[now].ch[dr],fa = t[now].fa,gf = t[fa].fa;
 20     t[son].fa = fa; t[fa].ch[dr^1] = son;
 21     t[now].ch[dr] = fa; t[fa].fa = now; t[now].fa = gf;
 22     if(t[gf].ch[0] == fa && gf != 0){t[gf].ch[0] = now;return;}
 23     if(t[gf].ch[1] == fa && gf != 0){t[gf].ch[1] = now;return;}
 24     root = now;
 25 }
 26 
 27 void push_down1(ll now){
 28     t[now].num+=t[now].lznum;
 29     t[L].lznum+=t[now].lznum;
 30     t[R].lznum+=t[now].lznum;
 31     t[now].lznum = 0;
 32 }
 33 
 34 void push_down2(ll now){
 35     t[now].data *= t[now].lzmul; t[now].data  %= mod;
 36     t[L].lzmul*=t[now].lzmul; t[L].lzmul %= mod;
 37     t[R].lzmul*=t[now].lzmul; t[R].lzmul %= mod;
 38     t[L].lzad*=t[now].lzmul; t[L].lzad %= mod;
 39     t[R].lzad*=t[now].lzmul; t[R].lzad %= mod;
 40     t[now].lzmul = 1;
 41 }
 42 
 43 void push_down3(ll now){
 44     t[now].data += t[now].lzad; t[now].data %= mod;
 45     t[L].lzad += t[now].lzad; t[L].lzad %= mod;
 46     t[R].lzad += t[now].lzad; t[R].lzad %= mod;
 47     t[now].lzad = 0;
 48 }
 49 
 50 ll fdnum(ll wt,ll now){
 51     if(t[now].lznum)push_down1(now);
 52     if(t[now].lzmul != 1)push_down2(now);
 53     if(t[now].lzad)push_down3(now);
 54     if(t[now].num == wt) return now;
 55     if(t[now].num > wt) return fdnum(wt,L);
 56     else return fdnum(wt,R);
 57 }
 58 
 59 stack <ll> sta;
 60 void splay(ll now,ll fwd = 0){
 61     ll fnow = now;
 62     while(fnow != fwd) sta.push(fnow),fnow=t[fnow].fa;
 63     while(!sta.empty()){
 64     ll k=sta.top();sta.pop();
 65     if(t[k].lznum)push_down1(k);
 66     if(t[k].lzmul != 1)push_down2(k);
 67     if(t[k].lzad)push_down3(k);
 68     }
 69     if(now == fwd)return;
 70     while(t[now].fa != fwd){
 71     if(t[t[now].fa].fa == fwd){
 72         if(t[t[now].fa].ch[1] == now) r0(now,0);
 73         else r0(now,1);
 74     }else{
 75         ll f = t[now].fa;
 76         if(t[f].ch[0] == now){
 77         if(t[t[f].fa].ch[0] == f) r0(f,1),r0(now,1);
 78         else r0(now,1),r0(now,0);
 79         }else{
 80         if(t[t[f].fa].ch[0] == f) r0(now,0),r0(now,1);
 81         else r0(f,0),r0(now,0);
 82         }
 83     }
 84     }
 85 }
 86 
 87 void insert(ll now,ll dt,ll wtis){
 88     while(true){
 89     if(t[now].lznum) push_down1(now);
 90     if(t[now].lzmul!=1) push_down2(now);
 91     if(t[now].lzad) push_down3(now);
 92     if(t[now].num > dt){
 93         if(t[now].ch[0])now = t[now].ch[0];
 94         else{t[now].ch[0]=wtis;t[wtis].fa = now;splay(now);break;}
 95     }else{
 96         if(t[now].ch[1])now = t[now].ch[1];
 97         else{t[now].ch[1]=wtis;t[wtis].fa = now;splay(now);break;}
 98     }
 99     }
100 }
101 
102 void mul(){
103     ll a,b;ll v; scanf("%lld%lld%lld",&a,&b,&v);v %= mod;
104     b = fdnum(b+1,root);splay(b);
105     if(a == 0){
106     push_down2(t[root].ch[0]);
107     push_down3(t[root].ch[0]);
108     t[t[root].ch[0]].lzmul = v;
109     } else{
110     a = fdnum(a-1,root);splay(a,root);
111     ll now = t[root].ch[0];
112     push_down2(R); push_down3(R);
113     t[R].lzmul = v;t[R].lzmul %= mod;
114     }
115 }
116 
117 void add(){
118     ll a,b;ll v; scanf("%lld%lld%lld",&a,&b,&v);v %= mod;
119     b = fdnum(b+1,root);splay(b);
120     if(a == 0) t[t[root].ch[0]].lzad += v,t[t[root].ch[0]].lzad %= mod;
121     else{
122     a=fdnum(a-1,root);splay(a,root);
123     ll now = t[root].ch[0];t[R].lzad += v;t[R].lzad %= mod;
124     }
125 }
126 
127 void mov(){
128     ll a,b; scanf("%lld%lld",&a,&b);
129     ll za = a,zb = b;
130     splay(fdnum(b,root));
131     ll nbb = fdnum(b+1,root);
132     splay(nbb,root);
133     t[t[t[root].ch[1]].ch[1]].fa = root;
134     t[root].ch[1] = t[t[root].ch[1]].ch[1];
135     t[root].data += t[nbb].data; t[root].data %= mod;
136     t[nbb].ch[0] = t[nbb].ch[1] = t[nbb].fa = 0;
137     t[nbb].num = a; t[nbb].data = 0; t[nbb].lznum = t[nbb].lzad = 0;
138     t[nbb].lzmul = 1;
139     splay(fdnum(b+2,root));
140     if(a == 0){
141     t[t[root].ch[0]].lznum++;
142     }else{
143     splay(fdnum(a-1,root),root);
144     t[t[t[root].ch[0]].ch[1]].lznum++;
145     }
146     insert(root,a,nbb);
147 }
148 
149 queue <ll> q;
150 ll sm[maxn];
151 int ddd[maxn];
152 void force(){
153     ll v; scanf("%lld",&v);v %= mod;sm[0] = 1;
154     for(int i=1;i<=2e5;i++) sm[i] = sm[i-1]*v,sm[i] %= mod;
155     q.push(root);
156     ll ans = 0;
157     while(!q.empty()){
158     ll k = q.front();q.pop();
159     if(t[k].lznum) push_down1(k);
160     if(t[k].lzmul!=1) push_down2(k);
161     if(t[k].lzad) push_down3(k);
162     //ddd[t[k].num] = t[k].data;
163     ans += sm[t[k].num]*t[k].data;
164     ans %= mod;
165     if(t[k].ch[0] != 0) q.push(t[k].ch[0]);
166     if(t[k].ch[1] != 0) q.push(t[k].ch[1]);
167     }
168     //for(int i=0;i<=10;i++) cout<<ddd[i]<<" ";
169     printf("%lld
",ans);
170 }
171 
172 void read(){
173     scanf("%lld",&n);
174     for(int i=1;i<=n;i++){
175     char C = getchar(),P=getchar();
176     while(P != ' '){C = P;P=getchar();}
177     switch(C){
178     case 'l':{mul();break;}
179     case 'd':{add();break;}
180     case 'x':{mov();break;}
181     default:{force();}
182     }
183     }
184 }
185 
186 int main(){
187     for(int i=1;i<=(int)2e5+10;i++) {t[++nb].num = i;insert(root,i,nb);}
188     read();
189     return 0;
190 }
原文地址:https://www.cnblogs.com/1-1-1-1/p/8117616.html