zoukankan      html  css  js  c++  java
  • bzoj3159决战 码农题 树剖套splay

    最近沉迷码农题无法自拔

    首先有一个暴力的想法:对于每个重链维护一个splay,需要翻转的连起来,翻转,接回去

    然后发现这样没问题。。。

    一条链只能跨log个重链,也就只有log个splay的子树参与重排,所以一次翻转只要log^2的时间

    需要维护的东西有点多

    头一次在splay上维护这么多乱七八糟的东西,写错了好几遍

    感觉学到不少debug技巧,也纠正了之前splay写法的一个小漏洞

    话说极限数据好像和miaom拍不过啊。。。但是我们都A了啊

    好烦啊不知道谁出锅了

      1 #include <bits/stdc++.h>
      2 #define num(x) (dep[x]-dep[top[x]]+1)
      3 #define ans tr[split(num(x),num(y))]
      4 #define rt root[RT]
      5 #define RT1 root[n+1]
      6 #define NO 800000
      7 #define N 800000
      8 #define INF 2000000000
      9 #define ll long long
     10 using namespace std;
     11 struct trnode
     12 {
     13     int size,min,max;ll sum;int plus,num;
     14     bool rev;
     15     trnode()
     16     {
     17         size=1;min=max=sum=plus=rev=num=0;
     18     }
     19 } tr[NO];
     20 int n,m,R,p,q,RT,x,y,z,RET,E,NODE,sttop,inv_x,inv_y;ll ret;
     21 int c[NO][2],fa[NO];bool die[N];
     22 int root[N],Fa[N],size[N],fir[N],top[N],dep[N],st[N],sz[N],lin[N];
     23 int nex[2*N],to[2*N];
     24 char cmd[10];
     25 void up(int x)
     26 {
     27     if(!x)
     28     {
     29         tr[0]=trnode();tr[0].size=0;
     30         return;
     31     }
     32     tr[x].size=tr[c[x][0]].size+tr[c[x][1]].size+1;
     33     tr[x].sum=tr[c[x][0]].sum+tr[c[x][1]].sum+(ll)tr[x].plus*tr[x].size+tr[x].num;
     34     tr[x].max=max(tr[c[x][0]].max,tr[c[x][1]].max)+tr[x].plus;
     35     tr[x].max=max(tr[x].max,tr[x].num+tr[x].plus);
     36     tr[x].min=tr[x].num;
     37     if(c[x][0]!=0)
     38         tr[x].min=min(tr[x].min,tr[c[x][0]].min);
     39     if(c[x][1]!=0)
     40         tr[x].min=min(tr[x].min,tr[c[x][1]].min);
     41     tr[x].min+=tr[x].plus;
     42 }
     43 void down(int x)
     44 {
     45     if(tr[x].rev)
     46         swap(c[x][0],c[x][1]),tr[c[x][0]].rev^=1,tr[c[x][1]].rev^=1,tr[x].rev=0;
     47     if(tr[x].plus)
     48         tr[c[x][0]].plus+=tr[x].plus,tr[c[x][1]].plus+=tr[x].plus,
     49         tr[x].num+=tr[x].plus,tr[x].plus=0,up(c[x][0]),up(c[x][1]);
     50 }
     51 void rot(int x)
     52 {
     53     down(fa[x]);down(x);
     54     int y=fa[x],k=c[y][1]==x;
     55     if(fa[y]) c[fa[y]][c[fa[y]][1]==y]=x;
     56     else rt=x;
     57     fa[x]=fa[y];fa[y]=x;
     58     c[y][k]=c[x][!k];
     59     if(c[x][!k])
     60         fa[c[x][!k]]=y;
     61     c[x][!k]=y;
     62     up(y);up(x);
     63 }
     64 void splay(int x,int z)
     65 {
     66     for(int y;(y=fa[x])!=z;rot(x))
     67     if(fa[y]!=z)
     68         rot(c[fa[y]][1]==y^c[y][1]==x?x:y);
     69 }
     70 int Find(int x)
     71 {
     72     if(x==0) return -1;
     73     if(x>tr[rt].size) return -1;
     74     int now=rt;
     75     while(down(now),tr[c[now][0]].size+1!=x)
     76     if(x<=tr[c[now][0]].size)
     77         now=c[now][0];
     78     else
     79         x-=tr[c[now][0]].size+1,now=c[now][1];
     80     return now;
     81 }
     82 int split(int x,int y)
     83 {
     84     if(x==1 && y==tr[rt].size)
     85         return rt;
     86     if(x==1) 
     87     { splay(Find(y+1),0);return c[rt][0];}
     88     if(y==tr[rt].size) 
     89     { splay(Find(x-1),0);return c[rt][1];}
     90     splay(Find(x-1),0);
     91     splay(Find(y+1),rt);
     92     return c[c[rt][1]][0];
     93 } 
     94 void upd(int x)
     95 {
     96     int len=0;
     97     while(x)
     98         lin[++len]=x,x=fa[x];
     99     for(int i=len;i;i--)
    100         down(lin[i]);
    101     for(int i=1;i<=len;i++)
    102         up(lin[i]);
    103 }
    104 int Split(int x,int y)
    105 {
    106     int p=split(x,y),q=fa[p];
    107     upd(p);
    108     fa[p]=0;c[q][c[q][1]==p]=0;
    109     upd(q); 
    110     splay(q,0);
    111     return p;
    112 }
    113 void work(int x,int y)
    114 {
    115     RT=top[x];int tem;
    116     if(cmd[2]=='c')
    117         tr[tem=split(num(x),num(y))].plus+=z,upd(tem);//?
    118     if(cmd[0]=='S')
    119         ret+=ans.sum;
    120     if(cmd[1]=='a')    ret=max(ret,(ll)ans.max);
    121     if(cmd[1]=='i')    RET=min(RET,ans.min);
    122     if(cmd[2]=='v')
    123     {
    124         int tem=Split(num(x),num(y));
    125         if(tem==rt) die[RT]=1;
    126         RT=n+1;
    127         if(!rt) rt=tem;
    128         else
    129         { 
    130             splay(Find(1),0);
    131             c[rt][0]=tem;fa[tem]=rt;
    132             splay(tem,0);
    133         }
    134     }
    135 }
    136 void add(int p,int q)
    137 {
    138     to[++E]=q;nex[E]=fir[p];fir[p]=E;
    139 }
    140 int build(int now,int fat)
    141 {
    142     size[now]=1;Fa[now]=fat;dep[now]=dep[fat]+1;
    143     for(int i=fir[now];i;i=nex[i])
    144     if(to[i]!=fat)
    145         size[now]+=build(to[i],now);
    146     return size[now];
    147 }
    148 void ins()
    149 {
    150     int now=rt;
    151     while(c[now][1]) now=c[now][1];
    152     c[now][1]=++NODE;fa[NODE]=now;
    153     tr[NODE]=trnode();
    154     splay(NODE,0);
    155 }
    156 void pou(int now,int Top)
    157 {
    158     top[now]=Top;
    159     if(Top==now)
    160         tr[++NODE]=trnode(),root[now]=NODE;
    161     else    
    162         RT=Top,ins();
    163     int id=0;
    164     for(int i=fir[now];i;i=nex[i])
    165     if(to[i]!=Fa[now])
    166     if(size[to[i]]>size[id])
    167         id=to[i];
    168     if(id) pou(id,Top);
    169     for(int i=fir[now];i;i=nex[i])
    170     if(to[i]!=Fa[now] && to[i]!=id)
    171         pou(to[i],to[i]);
    172 }
    173 int main()
    174 {
    175     scanf("%d%d%d",&n,&m,&R);
    176     for(int i=1;i<n;i++)
    177         scanf("%d%d",&p,&q),
    178         add(p,q),add(q,p);
    179     tr[0].size=0; 
    180     build(R,0);
    181     pou(R,R);
    182     for(int i=1;i<=m;i++)
    183     {
    184         if(i==4)
    185             int e=1;
    186         scanf("%s%d%d",cmd,&x,&y);
    187         if(cmd[2]=='c') scanf("%d",&z); 
    188         ret=0;RET=INF;sttop=0;
    189         while(top[x]!=top[y])
    190         {
    191             if(dep[top[x]]<dep[top[y]])    swap(x,y);
    192             work(top[x],x);
    193             st[++sttop]=top[x];sz[sttop]=num(x);
    194             x=Fa[top[x]];
    195         }
    196         if(dep[x]>dep[y])
    197             swap(x,y);
    198         if(cmd[2]=='v')
    199         {
    200             RT=top[x];
    201             inv_x=Find(num(x)-1);inv_y=Find(num(y)+1);
    202         }
    203         work(x,y);
    204         if(cmd[0]=='S' || cmd[1]=='a') printf("%lld
    ",ret);
    205         if(cmd[1]=='i') printf("%d
    ",RET); 
    206         if(cmd[2]=='v')
    207         {
    208             RT=n+1;
    209             tr[rt].rev^=1;
    210             int tem=Split(1,num(y)-num(x)+1);
    211             RT=top[x];
    212             if(inv_x==-1 && inv_y==-1)
    213                 rt=tem,die[RT]=0;
    214             else
    215             if(inv_x==-1)
    216             {
    217                 splay(inv_y,0);
    218                 c[rt][0]=tem;fa[tem]=rt;
    219                 splay(tem,0);
    220             }
    221             else
    222             if(inv_y==-1)
    223                 splay(inv_x,0),c[rt][1]=tem,fa[tem]=rt,splay(tem,0);
    224             else
    225                 splay(inv_x,0),splay(inv_y,rt),c[c[rt][1]][0]=tem,fa[tem]=c[rt][1],splay(tem,0);
    226             for(int i=sttop;i;i--)
    227             {
    228                 RT=n+1;
    229                 int tem=Split(1,sz[i]);
    230                 RT=st[i];
    231                 if(die[RT]) die[RT]=0,rt=tem;
    232                 else
    233                 {
    234                     splay(Find(1),0);
    235                     c[rt][0]=tem;fa[tem]=rt;splay(tem,0);
    236                 }
    237             }
    238         }
    239         root[n+1]=0;die[n+1]=0;
    240     }
    241     return 0;
    242 } 
  • 相关阅读:
    SqlHelper
    asp.net中窗口相关操作总结(javascript)
    ASP.NET顯示對話框
    为ASP.NET控件添加常用的JavaScript操作
    右键弹出菜单
    log4net的初使用
    QQ/MSN右下角弹出提示窗口
    简便无刷新文件上传系统
    简单的自动更新程序实
    SQL中的单记录函数
  • 原文地址:https://www.cnblogs.com/wanglichao/p/7298861.html
Copyright © 2011-2022 走看看