zoukankan      html  css  js  c++  java
  • COJ 0650 绝世难题(一) 可爱的仙人掌

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=620

    绝世难题(一) 可爱的仙人掌
    难度级别:E; 运行时间限制:1000ms; 运行空间限制:262144KB; 代码长度限制:2000000B
    试题描述

    ---“神犇是怎么样的。。。”

    ---“神犇就是这种**题拿过来半小时随便A。。。(๑•̀ㅂ•́)و✧”

     

    绝世难题之可爱的仙人掌


    -------------------------我是题目和吐槽的分割线-------------------------

     

    chx童鞋最近迷上了图论中的环,结果有一天他做梦都梦见了环。。。(¯﹃¯)

    ---“你最近一直研究我啊那你知道我有什么小名嘛?(,,• ₃ •,,)”

    ---“噗。。。我怎么知道你告诉我呗。。。Σ( ° △ °|||)︴”

    ---“其实嘛,我的小名叫做仙人掌了啊~”

    噗。。。chx脑中不禁脑补了一下。。。(ㆀ˘・з・˘)

    噗噗噗。。。chx心想好吧你说是就算是吧(⊙ ▽ ⊙)

    ---“其实呢,在一个无向连通图中呢,如果每一条边都只属于一个简单环,我们就把这个图叫做仙人掌。。。如果图中每一个连通块都是一个萌萌哒仙人掌且没有自环,那么我们就把这个图称作是沙漠。。。”

    呵呵。。。好吧真的 好好好形象啊!!!(๑•̀ㅂ•́)و✧

    如果一个无向图的每个连通块都是个仙人掌,且不存在自环,我们就称之为沙漠。

    现在呢,为了证明你是玩转仙人掌的神犇,chx给你 n 个结点,从 1 到 n 标号。

    初始时没有任何边,且每个结点 i 有个权值 wi (wi>0) 。每次进行如下操作之一:

     

    link v uw:在结点 v,u 间连一条权值为 w 的边。

    1≤v,u≤n 且 w 为正整数。

    如果连边完成后图仍为沙漠,则输出 "ok"(不含引号)。

    否则操作非法,撤销此次操作并输出 "failed"(不含引号)。

     

    cut v uw:在结点 v,u 间删掉一条权值为 w 的边。

    1≤v,u≤n 且 w 为正整数。

    如果存在这样的边则输出 "ok"(不含引号)(如果有多条权值为 w 的边删去任意一条)。

    否则操作非法,不进行操作并输出 "failed"(不含引号)。

     

    query1 vu:查询结点 v 到结点 u 的最短路信息。

    1≤v,u≤n。

    输出两个用空格隔开的整数 min,σ,分别代表最短路上点权的最小值、和。

    如果没有路可到达则 min=−1,σ=−1。

    如果最短路不唯一则 min=−2,σ=−2。

     

    query2 vu:查询以结点 v 为根,子仙人掌 u 的信息。

    1≤v,u≤n。

    以结点 v 为根,子仙人掌 u 的定义是,删掉v 到 u 之间的所有简单路径上的边之后,u 所在的连通块。

    输出两个用空格隔开的整数 min,σ,分别代表子仙人掌 u 中点权的最小值、和。

    如果 v,u 不连通则 min=−1,σ=−1。

     

    add1 v ud:把结点 v 到结点 u 的最短路上的每一个结点的权值都加上 d。

    1≤v,u≤n 且 d 为正整数。

    如果有路可到达且最短路唯一,则输出 "ok"(不含引号)

    否则操作非法,不进行操作并输出 "failed"(不含引号)。

     

    add2 v ud:把以结点 v 为根,子仙人掌 u 的每一个结点的权值都加上 d。

    1≤v,u≤n 且 d 为正整数。

    如果 v,u 在同一个连通块里,则输出 "ok"(不含引号)

    否则操作非法,不进行操作并输出 "failed"(不含引号)。

     

    现在你来负责搞定这个问题吧。。。

    输入
    第一行两个用空格隔开的正整数 n,m 表示一共有 n 个结点,m 个操作。

    接下来一行 n 个正整数,第 i 个正整数为 wi。

    接下来 m 行,每行代表一个操作。
    输出
    对于每个操作,输出相应的结果。
    输入示例
    11 23
    10 5 11 7 8 14 30 3 16 20 19
    link 1 2 5
    link 2 3 3
    link 3 4 7
    link 4 5 8
    link 2 6 10
    link 6 7 15
    link 4 7 3
    link 6 8 9
    link 6 8 6
    link 7 9 12
    link 9 11 10
    link 7 10 4
    link 9 10 8
    query1 6 11
    query1 2 10
    query2 8 7
    add1 8 5 100
    query1 1 7
    query2 8 7
    add2 11 7 1000
    query1 8 3
    add2 3 2 2333
    query1 1 5
    输出示例
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    ok
    -2 -2
    5 73
    16 85
    ok
    5 263
    16 185
    ok
    1005 4233
    ok
    1011 9907
    其他说明
    1≤n≤50000,1≤m≤250000。
    保证 link 和 cut 操作中的 w 满足 1≤w≤10000,所以关于边权的计算不会超出 32 位有符号整数范围。
    保证初始的 wi 不超过 109,保证所有 add1 和 add2 操作中的 d 之和不超过 109。


    ---真心吐槽这道题应该是本OJ代码长度最长的题呦→_→chx童鞋的极限缩行可是写了612行呢。。。

    题解:动态仙人掌哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

    最棒的仙人掌讲解看这里一共有四节:http://vfleaking.blog.163.com/blog/static/17480763420142176910962/

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<cstring>
      7 #define PAU putchar(' ')
      8 #define ENT putchar('
    ')
      9 #define MAXN 50005
     10 #define MAXM 250005
     11 #define is_NULL_tag(x) ((x)==0)
     12 #define is_NULL_info(x) (x.size==0)
     13 using namespace std;
     14 inline int read(){
     15     int x=0,sig=1;char ch=getchar();
     16     while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();}
     17     while(isdigit(ch))x=10*x+ch-'0',ch=getchar();
     18     return x*=sig;
     19 }
     20 inline void write(int x){
     21     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
     22     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
     23     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
     24 }
     25 char ch;
     26 inline void Pass_Pau(int x){while(x--) getchar();return;}
     27 int n,Q;
     28 struct Info{
     29     int mi,size;
     30     long long sum;
     31 };
     32 typedef int Tag;
     33 const Tag NULL_TAG=0;
     34 const Info NULL_INFO=(Info){2147483647,0,0};
     35 inline Info operator + (const Info &a,const Info &b){return (Info){std::min(a.mi,b.mi),a.size+b.size,a.sum+b.sum};}
     36 inline Info operator * (const Info &a,const Tag &b){return a.size ? (Info){a.mi+b,a.size,a.sum+1LL*a.size*b}: a;}
     37 struct splay_node{
     38     splay_node *s[2],*fa;
     39     Info x,sum;
     40     Tag tag,tag_sum;
     41     inline void add_tag(Tag t){
     42         x=x*t;sum=sum*t;
     43         tag=tag+t;tag_sum=tag_sum+t;
     44         return;
     45     }
     46     inline void down(){
     47         if(is_NULL_tag(tag)) return;
     48         if(s[0]) s[0]->add_tag(tag);
     49         if(s[1]) s[1]->add_tag(tag);
     50         tag=NULL_TAG;
     51         return;
     52     }
     53     inline void update(){
     54         sum=x;
     55         if(s[0]) sum=sum+s[0]->sum;
     56         if(s[1]) sum=sum+s[1]->sum;
     57         return;
     58     }
     59 };
     60 splay_node _splay[MAXN+MAXM];
     61 inline int get_parent(splay_node *x,splay_node *&fa){return (fa=x->fa) ? fa->s[1]==x : -1;}
     62 inline void rotate(splay_node *x){
     63     splay_node *fa,*gfa;
     64     int t1,t2;
     65     t1=get_parent(x,fa);
     66     t2=get_parent(fa,gfa);
     67     if((fa->s[t1]=x->s[t1^1])) fa->s[t1]->fa=fa;
     68     fa->fa=x;x->fa=gfa;x->s[t1^1]=fa;
     69     if(t2!=-1) gfa->s[t2]=x;
     70     fa->update();
     71     return;
     72 }
     73 inline void pushdown(splay_node *x){
     74     static splay_node *stack[MAXN+MAXM];
     75     int cnt=0;
     76     while(x){
     77         stack[cnt++]=x;
     78         x=x->fa;
     79     }
     80     while(cnt--) stack[cnt]->down();
     81     return;
     82 }
     83 inline splay_node * splay(splay_node *x){
     84     pushdown(x);
     85     while(1){
     86         splay_node *fa,*gfa;
     87         int t1,t2;
     88         t1=get_parent(x,fa);
     89         if(t1==-1) break;
     90         t2=get_parent(fa,gfa);
     91         if(t2==-1){
     92             rotate(x);break;
     93         }else if(t1==t2){
     94             rotate(fa);rotate(x);
     95         }else{
     96             rotate(x);rotate(x);
     97         };
     98     }
     99     x->update();
    100     return x;
    101 }
    102 inline splay_node * join(splay_node *a,splay_node *b){
    103     if(!a) return b;
    104     if(!b) return a;
    105     while(a->s[1]) a->down(),a=a->s[1];
    106     splay(a)->s[1]=b;b->fa=a;
    107     a->update();
    108     return a;
    109 }
    110 struct lcc_node;
    111 struct cycle{
    112     int A,B;
    113     lcc_node *ex;
    114 };
    115 struct lcc_node{
    116     lcc_node *s[2],*fa;
    117     lcc_node *first,*last;
    118     bool rev;
    119     bool isedge;
    120     bool mpath;
    121     bool hasmpath;
    122     bool mpathtag;
    123     bool hasmpathtag;
    124     bool hascyctag;
    125     bool hascyc;
    126     cycle *cyc;
    127     cycle *cyctag;
    128     int totlen;
    129     int len;
    130     int size;
    131     Info x,sum,sub,ex,all;
    132     Tag chain_tag,sub_tag,ex_tag_sum;
    133     inline void add_rev_tag(){
    134         std::swap(s[0],s[1]);
    135         std::swap(first,last);
    136         rev^=1;
    137         return;
    138     }
    139     inline void add_cyc_tag(cycle *c){
    140         if(isedge) cyc=c;
    141         cyctag=c;
    142         hascyctag=1;
    143         hascyc=c;
    144         return;
    145     }
    146     inline void add_mpath_tag(bool t){
    147         mpathtag=t;
    148         hasmpathtag=1;
    149         mpath=t&isedge;
    150         hasmpath=t&(isedge|(size>1));
    151         return;
    152     }
    153     inline void add_chain_tag(Tag t)
    154     {
    155         if(is_NULL_tag(t)) return;
    156         x=x*t;sum=sum*t;
    157         chain_tag=chain_tag+t;
    158         all=sum+sub;
    159         return;
    160     };
    161     inline void add_sub_tag(Tag t);
    162     inline void down(){
    163         if(rev){
    164             if(s[0]) s[0]->add_rev_tag();
    165             if(s[1]) s[1]->add_rev_tag();
    166             rev=0;
    167         }
    168         if(hascyctag){
    169             if(s[0]) s[0]->add_cyc_tag(cyctag);
    170             if(s[1]) s[1]->add_cyc_tag(cyctag);
    171             hascyctag=0;
    172         }
    173         if(hasmpathtag){
    174             if(s[0]) s[0]->add_mpath_tag(mpathtag);
    175             if(s[1]) s[1]->add_mpath_tag(mpathtag);
    176             hasmpathtag=0;
    177         }
    178         if(!is_NULL_tag(chain_tag)){
    179             if(s[0]) s[0]->add_chain_tag(chain_tag);
    180             if(s[1]) s[1]->add_chain_tag(chain_tag);
    181             chain_tag=NULL_TAG;
    182         }
    183         if(!is_NULL_tag(sub_tag)){
    184             if(s[0]) s[0]->add_sub_tag(sub_tag);
    185             if(s[1]) s[1]->add_sub_tag(sub_tag);
    186             sub_tag=NULL_TAG;
    187         }
    188         return;
    189     }
    190     inline void update();
    191 };
    192 lcc_node lcc[MAXN+MAXM];
    193 lcc_node *_node_tot;
    194 splay_node *splay_root[MAXN+MAXM];
    195 inline void lcc_node::add_sub_tag(Tag t){
    196     if(is_NULL_tag(t)) return;
    197     sub=sub*t;ex=ex*t;
    198     sub_tag=sub_tag+t;
    199     ex_tag_sum=ex_tag_sum+t;
    200     all=sum+sub;
    201     // add tag to splay_root
    202     int id=this-lcc;
    203     if(splay_root[id]){
    204         splay_root[id]->add_tag(t);
    205     }
    206 }
    207 inline void lcc_node::update(){
    208     totlen=len;
    209     hascyc=cyc;
    210     size=1;
    211     hasmpath=mpath;
    212     if(s[0]) totlen+=s[0]->totlen,hascyc|=s[0]->hascyc,size+=s[0]->size,hasmpath|=s[0]->hasmpath;
    213     if(s[1]) totlen+=s[1]->totlen,hascyc|=s[1]->hascyc,size+=s[1]->size,hasmpath|=s[1]->hasmpath;
    214     first=s[0]?s[0]->first:this;
    215     last=s[1]?s[1]->last:this;
    216     bool s0=s[0],s1=s[1];
    217     if(isedge){
    218         if(is_NULL_info(ex)){
    219             if(s0 && s1){
    220                 sum=s[0]->sum+s[1]->sum;
    221                 sub=s[0]->sub+s[1]->sub;
    222             }else if(s0){
    223                 sum=s[0]->sum;
    224                 sub=s[0]->sub;
    225             }else if(s[1]){
    226                 sum=s[1]->sum;
    227                 sub=s[1]->sub;
    228             }else{
    229                 sub=sum=NULL_INFO;
    230             }
    231         }else{
    232             if(s0 && s1){
    233                 sum=s[0]->sum+s[1]->sum;
    234                 sub=s[0]->sub+s[1]->sub+ex;
    235             }else if(s0){
    236                 sum=s[0]->sum;
    237                 sub=s[0]->sub+ex;
    238             }else if(s[1]){
    239                 sum=s[1]->sum;
    240                 sub=s[1]->sub+ex;
    241             }else{
    242                 sum=NULL_INFO;
    243                 sub=ex;
    244             }
    245         }
    246     }else{
    247         splay_node *root=splay_root[this-lcc];
    248         if(root){
    249             if(s0 && s1){
    250                 sum=s[0]->sum+s[1]->sum+x;
    251                 sub=s[0]->sub+s[1]->sub+root->sum;
    252             }else if(s0){
    253                 sum=s[0]->sum+x;
    254                 sub=s[0]->sub+root->sum;
    255             }else if(s[1]){
    256                 sum=s[1]->sum+x;
    257                 sub=s[1]->sub+root->sum;
    258             }else{
    259                 sub=root->sum;
    260                 sum=x;
    261             }
    262         }else{
    263             if(s0 && s1){
    264                 sum=s[0]->sum+s[1]->sum+x;
    265                 sub=s[0]->sub+s[1]->sub;
    266             }else if(s0){
    267                 sum=s[0]->sum+x;
    268                 sub=s[0]->sub;
    269             }else if(s[1]){
    270                 sum=s[1]->sum+x;
    271                 sub=s[1]->sub;
    272             }else{
    273                 sum=x;
    274                 sub=NULL_INFO;
    275             }
    276         }
    277     }
    278     all=sum+sub;
    279     return;
    280 };
    281 inline lcc_node * new_edge_node(int u,int v,int len){
    282     lcc_node *ret=++_node_tot;
    283     ret->s[0]=ret->s[1]=ret->fa=NULL;
    284     ret->first=ret->last=ret;
    285     ret->rev=0;
    286     ret->isedge=1;
    287     ret->hascyctag=ret->hascyc=0;
    288     ret->cyc=ret->cyctag=NULL;
    289     ret->totlen=ret->len=len;
    290     ret->size=1;
    291     ret->x=ret->sum=ret->sub=ret->ex=ret->all=NULL_INFO;
    292     ret->chain_tag=ret->sub_tag=ret->ex_tag_sum=NULL_TAG;
    293     return ret;
    294 }
    295 inline int get_parent(lcc_node *x,lcc_node *&fa){return (fa=x->fa) ? fa->s[0]==x?0:fa->s[1]==x?1:-1 : -1;}
    296 inline void rotate(lcc_node *x){
    297     int t1,t2;
    298     lcc_node *fa,*gfa;
    299     t1=get_parent(x,fa);
    300     t2=get_parent(fa,gfa);
    301     if((fa->s[t1]=x->s[t1^1])) fa->s[t1]->fa=fa;
    302     fa->fa=x;x->fa=gfa;x->s[t1^1]=fa;
    303     if(t2!=-1) gfa->s[t2]=x;
    304     fa->update();
    305     return;
    306 }
    307 inline void pushdown(lcc_node *x){
    308     static lcc_node *stack[MAXN+MAXM];
    309     int cnt=0;
    310     while(1){
    311         stack[cnt++]=x;
    312         lcc_node *fa=x->fa;
    313         if(!fa || (fa->s[0]!=x && fa->s[1]!=x)) break;
    314         x=fa;
    315     }
    316     while(cnt--) stack[cnt]->down();
    317     return;
    318 }
    319 inline lcc_node * splay(lcc_node *x){
    320     pushdown(x);
    321     while(1){
    322         int t1,t2;
    323         lcc_node *fa,*gfa;
    324         t1=get_parent(x,fa);
    325         if(t1==-1) break;
    326         t2=get_parent(fa,gfa);
    327         if(t2==-1){
    328             rotate(x);break;
    329         }else if(t1==t2){
    330             rotate(fa);rotate(x);
    331         }else{
    332             rotate(x);rotate(x);
    333         }
    334     }
    335     x->update();
    336     return x;
    337 }
    338 inline int getrank(lcc_node *x){
    339     splay(x);
    340     return 1+(x->s[0]?x->s[0]->size:0);
    341 }
    342 bool _attached[MAXN+MAXM];
    343 inline void detach_rch(lcc_node *x){
    344     if(!x->s[1]) return;
    345     int X=x-lcc;
    346     int id=x->s[1]->first-lcc;
    347     _attached[id]=1;
    348     splay_node *p=_splay+id;
    349     p->s[0]=splay_root[X];
    350     if(splay_root[X]) splay_root[X]->fa=p;
    351     p->s[1]=p->fa=NULL;
    352     p->x=x->s[1]->all;
    353     p->tag=p->tag_sum=NULL_TAG;
    354     p->update();
    355     splay_root[X]=p;
    356     x->s[1]=NULL;
    357     return;
    358 }
    359 inline void attach_rch(lcc_node *x,lcc_node *y,int id){
    360     int X=x-lcc;
    361     _attached[id]=0;
    362     splay_node *p=_splay+id;
    363     splay(p);
    364     if(p->s[0]) p->s[0]->fa=NULL;
    365     if(p->s[1]) p->s[1]->fa=NULL;
    366     splay_root[X]=join(p->s[0],p->s[1]);
    367     y->add_chain_tag(p->tag_sum);
    368     y->add_sub_tag(p->tag_sum);
    369     x->s[1]=y;
    370     return;
    371 }
    372 inline void attach_rch(lcc_node *x,lcc_node *y,int id,int id2){
    373     if(_attached[id]) attach_rch(x,y,id);
    374     else attach_rch(x,y,id2);
    375     return;
    376 }
    377 inline void attach_rch(lcc_node *x,lcc_node *y){
    378     if(!y) return;
    379     attach_rch(x,y,y->first-lcc);
    380     return;
    381 }
    382 inline lcc_node * access(lcc_node *x){
    383     lcc_node *ret=NULL;
    384     int last_ex_last_id;
    385     while(x){
    386         lcc_node *t=splay(x)->s[0];
    387         if(!t){
    388             detach_rch(x);
    389             if(ret) attach_rch(x,ret,ret->first-lcc,last_ex_last_id);
    390             ret=x;x->update();
    391             x=x->fa;
    392             continue;
    393         }
    394         while(t->s[1]) t->down(),t=t->s[1];
    395         if(!splay(t)->cyc){
    396             splay(x);
    397             detach_rch(x);
    398             if(ret) attach_rch(x,ret,ret->first-lcc,last_ex_last_id);
    399             ret=x;x->update();
    400             x=x->fa;
    401             continue;
    402         }
    403         cycle *c=t->cyc;
    404         lcc_node *A=lcc+c->A,*B=lcc+c->B,*ex=splay(c->ex);
    405         bool need_tag_down=false;
    406         lcc_node *B_ex;
    407         if(splay(B)->fa==A){
    408             detach_rch(B);
    409             B->s[1]=ex;ex->fa=B;B->update();
    410             need_tag_down=true;
    411             B_ex=B->s[0]->first;
    412         }else if(splay(A)->fa==B){
    413             std::swap(c->A,c->B);std::swap(A,B);ex->add_rev_tag();
    414             detach_rch(B);
    415             B->s[1]=ex;ex->fa=B;B->update();
    416             need_tag_down=true;
    417             B_ex=B->s[0]->last;
    418         }else{
    419             bool f=0;
    420             if(getrank(A)>getrank(B)){
    421                 std::swap(c->A,c->B);std::swap(A,B);ex->add_rev_tag();
    422                 f=1;
    423             }
    424             splay(A)->s[1]->fa=NULL;A->s[1]=NULL;A->update();
    425             splay(B);detach_rch(B);
    426             B->s[1]=ex;ex->fa=B;B->update();
    427             B_ex=f ? B->s[0]->last : B->s[0]->first;
    428         }
    429         // add tag to ex
    430         Tag tag_ex=splay(B_ex)->ex_tag_sum;
    431         B_ex->ex=NULL_INFO;
    432         B_ex->update();
    433         ex=splay(B)->s[1];
    434         ex->add_chain_tag(tag_ex);
    435         ex->add_sub_tag(tag_ex);
    436         B->update();
    437         splay(x);c->B=x-lcc;
    438         if(x->s[1]->totlen<x->s[0]->totlen) x->add_rev_tag();
    439         x->add_mpath_tag(x->s[1]->totlen==x->s[0]->totlen);
    440         x->down();
    441         c->ex=x->s[1];x->s[1]->fa=NULL;
    442         x->s[1]=NULL;
    443         x->update();
    444         lcc_node *tmp=splay(x->first);
    445         tmp->ex=c->ex->all;
    446         tmp->ex_tag_sum=NULL_TAG;
    447         tmp->update();
    448         splay(x);
    449         if(ret) attach_rch(x,ret,ret->first-lcc,last_ex_last_id);
    450         x->update();
    451         last_ex_last_id=c->ex->last-lcc;
    452         if(splay(A)->s[1]) ret=x,x=x->fa;
    453         else{
    454             if(need_tag_down) attach_rch(A,x,c->ex->last-lcc,x->first-lcc);
    455             A->s[1]=x;x->fa=A;A->update();
    456             ret=A;x=A->fa;
    457         }
    458     }
    459     return ret;
    460 }
    461 inline void setroot(int x){access(lcc+x)->add_rev_tag();};
    462 inline bool link(int u,int v,int len){
    463     if(u==v) return false;
    464     setroot(u);
    465     lcc_node *t=access(lcc+v);
    466     while(t->s[0]) t->down(),t=t->s[0];
    467     if(splay(t)!=lcc+u){
    468         lcc_node *p=new_edge_node(u,v,len);
    469         p->fa=splay(lcc+u);
    470         lcc[u].s[0]=p;
    471         lcc[u].fa=lcc+v;
    472         lcc[u].update();
    473         splay(lcc+v)->s[1]=lcc+u;
    474         lcc[v].update();
    475         return true;
    476     }
    477     if(t->hascyc) return false;
    478     lcc_node *ex=new_edge_node(u,v,len);
    479     cycle *c=new cycle((cycle){u,v,ex});
    480     ex->add_cyc_tag(c);
    481     t->add_cyc_tag(c);
    482     access(lcc+v);
    483     return true;
    484 }
    485 inline bool cut(int u,int v,int len){
    486     if(u==v) return false;
    487     setroot(u);
    488     lcc_node *t=access(lcc+v);
    489     while(t->s[0]) t->down(),t=t->s[0];
    490     if(splay(t)!=lcc+u) return false;
    491     if(!t->hascyc){
    492         if(t->size!=3) return false;
    493         if(t->totlen!=len) return false;
    494         t=t->s[1];
    495         if(t->s[0]) t->down(),t=t->s[0];
    496         splay(t);
    497         t->s[0]->fa=NULL;t->s[1]->fa=NULL;
    498         return true;
    499     }
    500     t=splay(lcc+v)->s[0];
    501     while(t->s[1]) t->down(),t=t->s[1];
    502     cycle *c=splay(t)->cyc;
    503     if(!c) return false;
    504     t=splay(lcc+u)->s[1];
    505     while(t->s[0]) t->down(),t=t->s[0];
    506     if(splay(t)->cyc!=c) return false;
    507     lcc_node *ex=c->ex;
    508     if(ex->size==1 && ex->len==len){
    509         t->add_cyc_tag(NULL);
    510         t->add_mpath_tag(0);
    511         delete c;
    512         return true;
    513     }
    514     if(t->size!=3 || t->len!=len) return false;
    515     // lcc[u].mpath == 0 !
    516     ex->add_cyc_tag(NULL);
    517     ex->add_mpath_tag(0);
    518     ex->add_rev_tag();
    519     ex->add_sub_tag(t->ex_tag_sum);
    520     ex->add_chain_tag(t->ex_tag_sum);
    521     lcc[u].fa=lcc[v].fa=NULL;
    522     while(ex->s[0]) ex->down(),ex=ex->s[0];
    523     splay(ex)->s[0]=lcc+u;lcc[u].fa=ex;ex->update();
    524     while(ex->s[1]) ex->down(),ex=ex->s[1];
    525     splay(ex)->s[1]=lcc+v;lcc[v].fa=ex;ex->update();
    526     delete c;
    527     return true;
    528 }
    529 inline Info query_path(int u,int v){
    530     setroot(u);
    531     lcc_node *t=access(lcc+v);
    532     while(t->s[0]) t->down(),t=t->s[0];
    533     if(splay(t)!=lcc+u) return (Info){-1,-1,-1};
    534     if(t->hasmpath) return (Info){-2,-2,-2};
    535     return t->sum;
    536 }
    537 inline Info query_subcactus(int u,int v){
    538     setroot(u);
    539     lcc_node *t=access(lcc+v);
    540     while(t->s[0]) t->down(),t=t->s[0];
    541     if(splay(t)!=lcc+u) return (Info){-1,-1,-1};
    542     Info ret=splay(lcc+v)->x;
    543     if(splay_root[v]) ret=ret+splay_root[v]->sum;
    544     return ret;
    545 }
    546 inline bool modify_path(int u,int v,Tag tag){
    547     setroot(u);
    548     lcc_node *t=access(lcc+v);
    549     while(t->s[0]) t->down(),t=t->s[0];
    550     if(splay(t)!=lcc+u) return false;
    551     if(t->hasmpath) return false;
    552     t->add_chain_tag(tag);
    553     return true;
    554 }
    555 inline bool modify_subcactus(int u,int v,Tag tag){
    556     setroot(u);
    557     lcc_node *t=access(lcc+v);
    558     while(t->s[0]) t->down(),t=t->s[0];
    559     if(splay(t)!=lcc+u) return false;
    560     splay(lcc+v);
    561     lcc[v].x=lcc[v].x*tag;
    562     if(splay_root[v]) splay_root[v]->add_tag(tag);
    563     lcc[v].update();
    564     return true;
    565 }
    566 void init(){
    567     n=read();Q=read();
    568     int i;
    569     static int w[MAXN];
    570     for(i=1;i<=n;i++){
    571         w[i]=read();
    572         lcc[i].first=lcc[i].last=lcc+i;
    573         lcc[i].size=1;
    574         lcc[i].x=lcc[i].sum=lcc[i].all=(Info){w[i],1,w[i]};
    575         lcc[i].sub=lcc[i].ex=NULL_INFO;
    576         lcc[i].chain_tag=lcc[i].sub_tag=lcc[i].ex_tag_sum=NULL_TAG;
    577     }
    578     _node_tot=lcc+n;
    579     return;
    580 }
    581 void work(){
    582     for(int i=1;i<=Q;i++){
    583         char ch=getchar();
    584         while(ch<=32) ch=getchar();
    585         if(ch=='l'){
    586             Pass_Pau(3);
    587             int u=read(),v=read(),len=read();
    588             puts(link(u,v,len) ? "ok" : "failed");
    589         }else if(ch=='c'){
    590             Pass_Pau(2);
    591             int u=read(),v=read(),len=read();
    592             puts(cut(u,v,len) ? "ok" : "failed");
    593         }else if(ch=='q'){
    594             Pass_Pau(4);
    595             ch=getchar();
    596             int u=read(),v=read();
    597             Info ret;
    598             ret=ch=='1' ? query_path(u,v) : query_subcactus(u,v);
    599             printf("%d %lld
    ",ret.mi,ret.sum);
    600         }else if(ch=='a'){
    601             Pass_Pau(2);
    602             ch=getchar();
    603             int u=read(),v=read(),val=read();
    604             puts((ch=='1'?modify_path(u,v,val):modify_subcactus(u,v,val)) ? "ok" : "failed");
    605         }else puts("error");
    606     }
    607     return;
    608 }
    609 void print(){
    610     return;
    611 }
    612 int main(){init();work();print();return 0;}
  • 相关阅读:
    逐步实现python版wc命令
    Linux中短横线(-)小记
    memcached启动脚本(class练习)
    nginx启动脚本(class练习)
    Python-类的方法
    re模块
    shutil模块
    时间模块(time/date)
    迭代器
    生成器
  • 原文地址:https://www.cnblogs.com/chxer/p/4483282.html
Copyright © 2011-2022 走看看