• 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 }
  • 相关阅读:
    js四舍五入
    文本框只能输入整数,输入其他的自动不显示
    [转]关于C#程序部署到Android
    ajax在火狐中传中文出现乱码的解决方法
    Vue 记录 Cannot read property '_withTask' of undefined
    vs中 VMDebugger未能加载导致异常
    System.InvalidOperationException: 支持“XXX”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。
    eclipse中将java项目转换成javaweb项目
    Android之SOAP协议与WebService服务器交互,解决超时的问题
    SymmetricDS 快速和灵活的数据库复制
  • 原文地址:https://www.cnblogs.com/1-1-1-1/p/8117616.html
Copyright © 2020-2023  润新知