• BZOJ3159: 决战(FHQ Treap)


    传送门

    解题思路:

    算是补坑了,这题除了Invert以外就可以树剖线段树解决了。

    考虑Invert操作,延续先前树链剖分的做法,考虑先前算法的瓶颈。

    最暴力的方法是暴力交换权值,然而这种方法忽略了当前树链剖分序的一个性质,那就是很多部分的树链是连续的,而且仅有$O(lg n)$个区间。

    考虑只有一个区间的做法,就很显然是区间翻转(这个不会搞的话你是怎么做到这道题的),于是,由于区间个数并不多,我们大胆猜想:正确的解法就是考虑翻如何转这些不连续区间

    由于链区间具有一定的连续性,且我们需要翻转其权值,考虑更换我们所使用的数据结构,Splay和FHQ Treap都可以,我个人更倾向于使用后者(因为好写)。

    现在问题瓶颈就是如何翻转不连续的区间权值。

    其实方法很简单,将这$O(lg n)$个拼接在一起,翻转,再重新安回去,很显然这样做的时间复杂度是$O((lg n)^2))$的。

    考虑具体的操作,由于下标索引在拆树的时候可能改变非常恶心,所以我们预处理出x-y中所有链区间,按dfs序排序,倒着拆,把x到lca上的树链翻转后拼接,再与y到lca上的树链翻转。最后再翻转,正着安回去。

    大概就可以愉快地AC了。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<algorithm>
      5 #define lll tr[spc].ls
      6 #define rrr tr[spc].rs
      7 typedef long long lnt;
      8 struct chain{
      9     int ind;
     10     int len;
     11     bool x;
     12 }ch[100010];
     13 struct trnt{
     14     int ls,rs;
     15     int lzt;
     16     int wgt;
     17     int rnd;
     18     lnt lzta;
     19     lnt val;
     20     lnt sum;
     21     lnt maxval,minval;
     22     void rediff(int seed){
     23         ls=rs=lzt=0;
     24         lzta=val=sum=maxval=minval=0;
     25         rnd=seed+rand()%500+1;
     26         wgt=1;
     27         return ;
     28     }
     29 }tr[1000010];
     30 struct pnt{
     31     int hd;
     32     int fa;
     33     int tp;
     34     int dep;
     35     int ind;
     36     int mxs;
     37     int wgt;
     38 }p[100010];
     39 struct ent{
     40     int twd;
     41     int lst;
     42 }e[100010];
     43 int cnt;
     44 int siz;
     45 int dfn;
     46 int top;
     47 int n,m,r;
     48 char cmd[100];
     49 int rootl,rootr,rootm,root;
     50 int pos[100010],size[100010];
     51 int cmp(chain a,chain b){
     52     return a.ind<b.ind;
     53 }
     54 void ade(int f,int t){
     55     cnt++;
     56     e[cnt].twd=t;
     57     e[cnt].lst=p[f].hd;
     58     p[f].hd=cnt;
     59     return ;
     60 }
     61 void push_up(int spc){
     62     tr[spc].wgt=1;
     63     tr[spc].minval=tr[spc].maxval=tr[spc].sum=tr[spc].val;
     64     if(lll){
     65         tr[spc].wgt+=tr[lll].wgt;
     66         tr[spc].sum+=tr[lll].sum;
     67         tr[spc].minval=std::min(tr[spc].minval,tr[lll].minval);
     68         tr[spc].maxval=std::max(tr[spc].maxval,tr[lll].maxval);
     69     }
     70     if(rrr){
     71         tr[spc].wgt+=tr[rrr].wgt;
     72         tr[spc].sum+=tr[rrr].sum;
     73         tr[spc].minval=std::min(tr[spc].minval,tr[rrr].minval);
     74         tr[spc].maxval=std::max(tr[spc].maxval,tr[rrr].maxval);
     75     }
     76     return ;
     77 }
     78 void add(int spc,lnt val){
     79     if(!spc){
     80         return ;
     81     }
     82     tr[spc].val+=val;
     83     tr[spc].lzta+=val;
     84     tr[spc].maxval+=val;
     85     tr[spc].minval+=val;
     86     tr[spc].sum+=val*tr[spc].wgt;
     87     return ;
     88 }
     89 void trr(int spc){
     90     if(!spc){
     91         return ;
     92     }
     93     std::swap(lll,rrr);
     94     tr[spc].lzt^=1;
     95     return ;
     96 }
     97 void push_down(int spc){
     98     if(tr[spc].lzt){
     99         trr(lll);
    100         trr(rrr);
    101         tr[spc].lzt=0;
    102     }
    103     if(tr[spc].lzta){
    104         add(lll,tr[spc].lzta);
    105         add(rrr,tr[spc].lzta);
    106         tr[spc].lzta=0;
    107     }
    108     return ;
    109 }
    110 void build(int l,int r,int &spc,int seed){
    111     if(l>r){
    112         return ;
    113     }
    114     int mid=(l+r)>>1;
    115     spc=++siz;
    116     tr[spc].rediff(seed);
    117     build(l,mid-1,lll,tr[spc].rnd);
    118     build(mid+1,r,rrr,tr[spc].rnd);
    119     push_up(spc);
    120     return ;
    121 }
    122 void split(int spc,int &ll,int &rr,int k){
    123     if(!spc){
    124         ll=rr=0;
    125         return ;
    126     }
    127     push_down(spc);
    128     if(tr[lll].wgt<k){
    129         ll=spc;
    130         split(rrr,rrr,rr,k-tr[lll].wgt-1);
    131     }else{
    132         rr=spc;
    133         split(lll,ll,lll,k);
    134     }
    135     push_up(spc);
    136     return ;
    137 }
    138 int merge(int ll,int rr){
    139     if(!ll||!rr){
    140         return ll|rr;
    141     }else{
    142         if(tr[ll].rnd<tr[rr].rnd){
    143             push_down(ll);
    144             tr[ll].rs=merge(tr[ll].rs,rr);
    145             push_up(ll);
    146             return ll;
    147         }else{
    148             push_down(rr);
    149             tr[rr].ls=merge(ll,tr[rr].ls);
    150             push_up(rr);
    151             return rr;
    152         }
    153     }
    154     return 0;
    155 }
    156 void Basic_dfs(int x,int f){
    157     p[x].fa=f;
    158     p[x].wgt=1;
    159     p[x].dep=p[f].dep+1;
    160     int maxs(-1);
    161     for(int i=p[x].hd;i;i=e[i].lst){
    162         int to=e[i].twd;
    163         if(to==f){
    164             continue;
    165         }
    166         Basic_dfs(to,x);
    167         p[x].wgt+=p[to].wgt;
    168         if(p[to].wgt>maxs){
    169             p[x].mxs=to;
    170             maxs=p[to].wgt;
    171         }
    172     }
    173     return ;
    174 }
    175 void Build_dfs(int x,int t){
    176     if(!x){
    177         return ;
    178     }
    179     p[x].tp=t;
    180     p[x].ind=++dfn;
    181     Build_dfs(p[x].mxs,t);
    182     for(int i=p[x].hd;i;i=e[i].lst){
    183         int to=e[i].twd;
    184         if(p[to].ind){
    185             continue;
    186         }
    187         Build_dfs(to,to);
    188     }
    189     return ;
    190 }
    191 void Increase(int x,int y,lnt z){
    192     while(p[x].tp!=p[y].tp){
    193         if(p[p[x].tp].dep<p[p[y].tp].dep){
    194             std::swap(x,y);
    195         }
    196         int S(p[p[x].tp].ind-1),T(p[x].ind);
    197         split(root,rootl,rootr,T);
    198         split(rootl,rootl,rootm,S);
    199         add(rootm,z);
    200         root=merge(rootl,merge(rootm,rootr));
    201         x=p[p[x].tp].fa;
    202         
    203     }
    204     if(p[x].dep>p[y].dep){
    205         std::swap(x,y);
    206     }
    207     int S(p[x].ind-1),T(p[y].ind);
    208     split(root,rootl,rootr,T);
    209     split(rootl,rootl,rootm,S);
    210     add(rootm,z);
    211     root=merge(rootl,merge(rootm,rootr));
    212     return ;
    213 }
    214 void Invert(int x,int y){
    215     top=0;
    216     if(p[x].ind>p[y].ind){
    217         std::swap(x,y);
    218     }
    219     int lca(r);
    220     int tmpx(x),tmpy(y);
    221     while(p[x].tp!=p[y].tp){
    222         if(p[p[x].tp].dep>p[p[y].tp].dep){
    223             top++;
    224             ch[top].ind=p[p[x].tp].ind;
    225             ch[top].len=p[x].ind-p[p[x].tp].ind+1;
    226             ch[top].x=true;
    227             x=p[p[x].tp].fa;
    228         }else{
    229             top++;
    230             ch[top].ind=p[p[y].tp].ind;
    231             ch[top].len=p[y].ind-p[p[y].tp].ind+1;
    232             ch[top].x=false;
    233             y=p[p[y].tp].fa;
    234         }
    235     }
    236     if(p[x].dep<=p[y].dep){
    237         top++;
    238         ch[top].ind=p[x].ind;
    239         ch[top].len=p[y].ind-p[x].ind+1;
    240         ch[top].x=false;
    241     }else{
    242         top++;
    243         ch[top].ind=p[y].ind;
    244         ch[top].len=p[x].ind-p[y].ind+1;
    245         ch[top].x=true;
    246     }
    247     std::sort(ch+1,ch+top+1,cmp);
    248     int tmptop(top);
    249     int root_(0);
    250     while(top){
    251         int S(ch[top].ind-1),T(ch[top].ind+ch[top].len-1);
    252         split(root,rootl,rootr,T);
    253         split(rootl,rootl,rootm,S);
    254         root=merge(rootl,rootr);
    255         if(ch[top].x){
    256             trr(rootm);
    257         }
    258         root_=merge(rootm,root_);
    259         top--;
    260     }
    261     trr(root_);
    262     top=1;
    263     while(top<=tmptop){
    264         int S(ch[top].ind-1);
    265         split(root,rootl,rootr,S);
    266         split(root_,rootm,root_,ch[top].len);
    267         if(ch[top].x){
    268             trr(rootm);
    269         }
    270         root=merge(rootl,merge(rootm,rootr));
    271         top++;
    272     }
    273     return ;
    274 }
    275 lnt Sum(int x,int y){
    276     lnt ans(0);
    277     while(p[x].tp!=p[y].tp){
    278         if(p[p[x].tp].dep<p[p[y].tp].dep){
    279             std::swap(x,y);
    280         }
    281         int S(p[p[x].tp].ind-1),T(p[x].ind);
    282         split(root,rootl,rootr,T);
    283         split(rootl,rootl,rootm,S);
    284         ans=ans+tr[rootm].sum;
    285         root=merge(rootl,merge(rootm,rootr));
    286         x=p[p[x].tp].fa;
    287     }
    288     if(p[x].dep>p[y].dep){
    289         std::swap(x,y);
    290     }
    291     int S(p[x].ind-1),T(p[y].ind);
    292     split(root,rootl,rootr,T);
    293     split(rootl,rootl,rootm,S);
    294     ans=ans+tr[rootm].sum;
    295     root=merge(rootl,merge(rootm,rootr));
    296     return ans;
    297 }
    298 lnt Major(int x,int y){
    299     lnt ans(-0x3f3f3f3f3f3fll);
    300     while(p[x].tp!=p[y].tp){
    301         if(p[p[x].tp].dep<p[p[y].tp].dep){
    302             std::swap(x,y);
    303         }
    304         int S(p[p[x].tp].ind-1),T(p[x].ind);
    305         split(root,rootl,rootr,T);
    306         split(rootl,rootl,rootm,S);
    307         ans=std::max(ans,tr[rootm].maxval);
    308         root=merge(rootl,merge(rootm,rootr));
    309         x=p[p[x].tp].fa;
    310     }
    311     if(p[x].dep>p[y].dep){
    312         std::swap(x,y);
    313     }
    314     int S(p[x].ind-1),T(p[y].ind);
    315     split(root,rootl,rootr,T);
    316     split(rootl,rootl,rootm,S);
    317     ans=std::max(ans,tr[rootm].maxval);
    318     root=merge(rootl,merge(rootm,rootr));
    319     return ans;
    320 }
    321 lnt Minor(int x,int y){
    322     lnt ans(0x3f3f3f3f3f3fll);
    323     while(p[x].tp!=p[y].tp){
    324         if(p[p[x].tp].dep<p[p[y].tp].dep){
    325             std::swap(x,y);
    326         }
    327         int S(p[p[x].tp].ind-1),T(p[x].ind);
    328         split(root,rootl,rootr,T);
    329         split(rootl,rootl,rootm,S);
    330         ans=std::min(ans,tr[rootm].minval);
    331         root=merge(rootl,merge(rootm,rootr));
    332         x=p[p[x].tp].fa;
    333     }
    334     if(p[x].dep>p[y].dep){
    335         std::swap(x,y);
    336     }
    337     int S(p[x].ind-1),T(p[y].ind);
    338     split(root,rootl,rootr,T);
    339     split(rootl,rootl,rootm,S);
    340     ans=std::min(ans,tr[rootm].minval);
    341     root=merge(rootl,merge(rootm,rootr));
    342     return ans;
    343 }
    344 void pia(int spc){
    345     if(!spc){
    346         return ;
    347     }
    348     push_down(spc);
    349     pia(lll);
    350     printf("%lld ",tr[spc].val);
    351     pia(rrr);
    352     return ;
    353 }
    354 int main(){
    355     scanf("%d%d%d",&n,&m,&r);
    356     for(int i=1;i<=n;++i){
    357         int a,b;
    358         scanf("%d%d",&a,&b);
    359         ade(a,b);
    360         ade(b,a);
    361     }
    362     build(1,n,root,0);
    363     Basic_dfs(r,r);
    364     Build_dfs(r,r);
    365     int pro(0);
    366     while(m--){
    367         int x,y,z;
    368         scanf("%s",cmd+1);
    369         if(cmd[1]=='I'){
    370             if(cmd[3]=='c'){
    371                 scanf("%d%d%d",&x,&y,&z);
    372                 Increase(x,y,lnt(z));
    373             }
    374             if(cmd[3]=='v'){
    375                 scanf("%d%d",&x,&y);
    376                 Invert(x,y);
    377             }
    378         }
    379         if(cmd[1]=='S'){
    380             scanf("%d%d",&x,&y);
    381             printf("%lld
    ",Sum(x,y));
    382         }
    383         if(cmd[1]=='M'){
    384             if(cmd[2]=='a'){
    385                 scanf("%d%d",&x,&y);
    386                 printf("%lld
    ",Major(x,y));
    387             }
    388             if(cmd[2]=='i'){
    389                 scanf("%d%d",&x,&y);
    390                 printf("%lld
    ",Minor(x,y));
    391             }
    392         }
    393     }
    394     return 0;
    395 }
  • 相关阅读:
    js的继承实现方式
    jdbc调用通用存储过程完成分页
    最近在忙些什么......
    【转】说服下属的“攻心术”
    设计模式原则详解
    【转】职场学做“功夫熊猫”
    内核初始化优化宏 ,初始化顺序, __init,__devexit等
    Linux 嵌入式启动以及优化
    每个程序员都该知道的10大编程格言
    linux 用户空间 和 内核空间 延时函数
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/11160430.html
Copyright © 2020-2023  润新知