zoukankan      html  css  js  c++  java
  • [CodeChef-QTREE]Queries on tree again!

    题目大意:
      给定一个环长为奇数的带权基环树,支持以下两种操作:
        1.两点间最短路取反;
        2.两点间最短路求最大子段和。
    思路:
      首先找出环,然后对每一个外向树轻重链剖分,
      用线段树维护每一个区间的和、前缀和最值、后缀和最值及子段最值。
      每次修改时,分下列两种情况讨论:
        1.两个点在同一棵外向树上,按照普通的树链剖分修改,线段树上打取反的标记。
        2.两个点再不同外向树上,先各自沿着链往上跳,然后都跳到环上的时候,可以将两个点在环中的序号减一减,对环长取模,看看哪个小。
      查询时大致和修改一样,但是合并两个区间的时候很麻烦,要注意考虑完全。
    细节:
      1.找环可以在DFS的时候和树剖一起完成,也可以用并查集写,两个效率差不多。
      2.标记可以打好几次,所以不能简单地把标记赋值为true,而是每次取反。
    这题代码量比较大,vjudge上除了周骏东都是10K左右。网上的题解也很少,中英文都没有找到。
    一开始写挂的地方特别多,对拍对了好多次才排出所有的错。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<vector>
      4 inline int getint() {
      5     char ch;
      6     bool neg=false;
      7     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
      8     int x=ch^'0';
      9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     10     return neg?-x:x;
     11 }
     12 const int V=100001;
     13 struct Edge {
     14     int to,w;
     15 };
     16 std::vector<Edge> e[V];
     17 inline void add_edge(const int u,const int v,const int w) {
     18     e[u].push_back((Edge){v,w});
     19 }
     20 int par[V],size[V],son[V],cyc[V],id[V],w[V],root[V],dep[V],top[V];
     21 int cnt_cyc,cnt;
     22 bool on_cycle[V];
     23 bool dfs1(const int x,const int p) {
     24     if(par[x]||(x==1&&p!=0)) {
     25         on_cycle[x]=true;
     26         return true;
     27     } 
     28     size[x]=1;
     29     par[x]=p;
     30     bool flag=false;
     31     for(unsigned i=0;i<e[x].size();i++) {
     32         int &y=e[x][i].to;
     33         if(y==p||on_cycle[y]) continue;
     34         if(dfs1(y,x)) {
     35             par[x]=0;
     36             id[y]=++cnt;
     37             w[cnt]=e[x][i].w;
     38             if(on_cycle[x]) {
     39                 flag=true;
     40             } else {
     41                 on_cycle[x]=true;
     42             }
     43         } else {
     44             size[x]+=size[y];
     45             if(size[y]>size[son[x]]) son[x]=y;
     46         }
     47     }
     48     if(on_cycle[x]) cyc[++cnt_cyc]=x;
     49     return on_cycle[x]^flag;
     50 }
     51 int rt;
     52 void dfs2(const int x) {
     53     dep[x]=dep[par[x]]+1;
     54     top[x]=x==son[par[x]]?top[par[x]]:x;
     55     root[x]=cyc[rt];
     56     if(son[x]) {
     57         id[son[x]]=++cnt;
     58         dfs2(son[x]);
     59     }
     60     for(unsigned i=0;i<e[x].size();i++) {
     61         int &y=e[x][i].to;
     62         if(y==par[x]||on_cycle[y]) continue;
     63         if(y==son[x]) {
     64             w[id[y]]=e[x][i].w;
     65             continue;
     66         }
     67         id[y]=++cnt;
     68         w[cnt]=e[x][i].w;
     69         dfs2(y);
     70     }
     71 }
     72 void dfs3(const int x,const int p) {
     73     par[x]=p;
     74     son[x]=0;
     75     size[x]=1;
     76     for(unsigned i=0;i<e[x].size();i++) {
     77         int &y=e[x][i].to;
     78         if(y==p||on_cycle[y]) continue;
     79         dfs3(y,x);
     80         size[x]+=size[y];
     81         if(size[y]>size[son[x]]) son[x]=y;
     82     }
     83 }
     84 class SegmentTree {
     85     private:
     86         int left[V<<1],right[V<<1];
     87         long long sum[V<<1],submax[V<<1],submin[V<<1],premax[V<<1],premin[V<<1],sufmax[V<<1],sufmin[V<<1];
     88         bool neg[V<<1];
     89         int sz,newnode() {
     90             return ++sz;
     91         }
     92         void negate(long long &x) {
     93             x=-x;
     94         }
     95         void reverse(const int p) {
     96             negate(sum[p]);
     97             negate(submax[p]);
     98             negate(submin[p]);
     99             std::swap(submax[p],submin[p]);
    100             negate(premax[p]);
    101             negate(premin[p]);
    102             std::swap(premax[p],premin[p]);
    103             negate(sufmax[p]);
    104             negate(sufmin[p]);
    105             std::swap(sufmax[p],sufmin[p]);
    106         }
    107         void push_up(const int p) {
    108             sum[p]=sum[left[p]]+sum[right[p]];
    109             submax[p]=std::max(std::max(submax[left[p]],submax[right[p]]),sufmax[left[p]]+premax[right[p]]);
    110             submin[p]=std::min(std::min(submin[left[p]],submin[right[p]]),sufmin[left[p]]+premin[right[p]]);
    111             premax[p]=std::max(premax[left[p]],sum[left[p]]+premax[right[p]]);
    112             premin[p]=std::min(premin[left[p]],sum[left[p]]+premin[right[p]]);
    113             sufmax[p]=std::max(sufmax[right[p]],sum[right[p]]+sufmax[left[p]]);
    114             sufmin[p]=std::min(sufmin[right[p]],sum[right[p]]+sufmin[left[p]]);
    115         }
    116         void push_down(const int p) {
    117             if(!neg[p]) return;
    118             reverse(left[p]);
    119             reverse(right[p]);
    120             neg[p]=false;
    121             neg[left[p]]=!neg[left[p]];
    122             neg[right[p]]=!neg[right[p]];
    123         }
    124     public:
    125         struct Ans {
    126             long long sum,pre,sub,suf;
    127         };
    128         int root;
    129         void build(int &p,const int b,const int e) {
    130             p=newnode();
    131             if(b==e) {
    132                 sum[p]=w[b];
    133                 submax[p]=premax[p]=sufmax[p]=std::max(w[b],0);
    134                 submin[p]=premin[p]=sufmin[p]=std::min(w[b],0);
    135                 return;
    136             }
    137             int mid=(b+e)>>1;
    138             build(left[p],b,mid);
    139             build(right[p],mid+1,e);
    140             push_up(p);
    141         }
    142         void modify(const int p,const int b,const int e,const int l,const int r) {
    143             if((b==l)&&(e==r)) {
    144                 reverse(p);
    145                 neg[p]=!neg[p];
    146                 return;
    147             }
    148             push_down(p);
    149             int mid=(b+e)>>1;
    150             if(l<=mid) modify(left[p],b,mid,l,std::min(mid,r));
    151             if(r>mid) modify(right[p],mid+1,e,std::max(mid+1,l),r);
    152             push_up(p);
    153         }
    154         Ans query(const int p,const int b,const int e,const int l,const int r) {
    155             if((b==l)&&(e==r)) {
    156                 return (Ans){sum[p],premax[p],submax[p],sufmax[p]};
    157             }
    158             push_down(p);
    159             int mid=(b+e)>>1;
    160             long long leftsum=0,leftpre=0,leftsub=0,leftsuf=0,rightsum=0,rightpre=0,rightsub=0,rightsuf=0;
    161             if(l<=mid) {
    162                 Ans tmp=query(left[p],b,mid,l,std::min(mid,r));
    163                 leftsum=tmp.sum;
    164                 leftpre=tmp.pre;
    165                 leftsub=tmp.sub;
    166                 leftsuf=tmp.suf;
    167             }
    168             if(r>mid) {
    169                 Ans tmp=query(right[p],mid+1,e,std::max(mid+1,l),r);
    170                 rightsum=tmp.sum;
    171                 rightpre=tmp.pre;
    172                 rightsub=tmp.sub;
    173                 rightsuf=tmp.suf;
    174             }
    175             long long sum,pre,sub,suf;
    176             sum=leftsum+rightsum;
    177             pre=std::max(leftpre,leftsum+rightpre);
    178             sub=std::max(std::max(leftsub,rightsub),leftsuf+rightpre);
    179             suf=std::max(rightsuf,rightsum+leftsuf);
    180             return (Ans){sum,pre,sub,suf};
    181         }
    182 };
    183 SegmentTree t;
    184 int n;
    185 inline void modify(int x,int y) {
    186     if(root[x]!=root[y]) {
    187         while(top[x]!=root[x]) {
    188             t.modify(t.root,1,n,id[top[x]],id[x]);
    189             x=par[top[x]];
    190         }
    191         if(x!=top[x]) {
    192             t.modify(t.root,1,n,id[son[top[x]]],id[x]);
    193             x=top[x];
    194         }
    195         while(top[y]!=root[y]) {
    196             t.modify(t.root,1,n,id[top[y]],id[y]);
    197             y=par[top[y]];
    198         }
    199         if(y!=top[y]) {
    200             t.modify(t.root,1,n,id[son[top[y]]],id[y]);
    201             y=top[y];
    202         }
    203     } else {
    204         while(top[x]!=top[y]) {
    205             if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    206             t.modify(t.root,1,n,id[top[x]],id[x]);
    207             x=par[top[x]];
    208         }
    209         if(x!=y) {
    210             if(dep[x]<dep[y]) std::swap(x,y);
    211             t.modify(t.root,1,n,id[son[y]],id[x]);
    212         }
    213         return;
    214     }
    215     if((id[y]-id[x]+cnt_cyc)%cnt_cyc>(id[x]-id[y]+cnt_cyc)%cnt_cyc) std::swap(x,y);
    216     if(id[x]<id[y]) {
    217         t.modify(t.root,1,n,id[x],id[y]-1);
    218     } else {
    219         t.modify(t.root,1,n,id[x],cnt_cyc);
    220         if(id[y]!=1) t.modify(t.root,1,n,1,id[y]-1);
    221     }
    222 }
    223 inline long long query(int x,int y) {
    224     long long lastsum=0,lastpre=0,lastsub=0,lastsuf=0,nextsum=0,nextpre=0,nextsub=0,nextsuf=0;
    225     long long ans=0;
    226     if(root[x]!=root[y]) {
    227         while(top[x]!=root[x]) {
    228             SegmentTree::Ans tmp=t.query(t.root,1,n,id[top[x]],id[x]);
    229             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
    230             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
    231             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
    232             lastsum+=tmp.sum;
    233             ans=std::max(ans,lastsub);
    234             x=par[top[x]];
    235         }
    236         if(x!=top[x]) {
    237             SegmentTree::Ans tmp=t.query(t.root,1,n,id[son[top[x]]],id[x]);
    238             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
    239             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
    240             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
    241             lastsum+=tmp.sum;
    242             ans=std::max(ans,lastsub);
    243             x=top[x];
    244         }
    245         while(top[y]!=root[y]) {
    246             SegmentTree::Ans tmp=t.query(t.root,1,n,id[top[y]],id[y]);
    247             nextsub=std::max(std::max(nextsub,tmp.sub),nextpre+tmp.suf);
    248             nextpre=std::max(tmp.pre,nextpre+tmp.sum);
    249             nextsuf=std::max(nextsuf,nextsum+tmp.suf);
    250             nextsum+=tmp.sum;
    251             ans=std::max(ans,nextsub);
    252             y=par[top[y]];
    253         }
    254          if(y!=top[y]) {
    255             SegmentTree::Ans tmp=t.query(t.root,1,n,id[son[top[y]]],id[y]);
    256             nextsub=std::max(std::max(nextsub,tmp.sub),nextpre+tmp.suf);
    257             nextpre=std::max(tmp.pre,nextpre+tmp.sum);
    258             nextsuf=std::max(nextsuf,nextsum+tmp.suf);
    259             nextsum+=tmp.sum;
    260             ans=std::max(ans,nextsub);
    261             y=top[y];
    262         }
    263     } else {
    264         while(top[x]!=top[y]) {
    265             if(dep[top[x]]<dep[top[y]]) {
    266                 std::swap(x,y);
    267                 std::swap(lastsum,nextsum);
    268                 std::swap(lastsub,nextsub);
    269                 std::swap(lastpre,nextpre);
    270                 std::swap(lastsuf,nextsuf);
    271             }
    272             SegmentTree::Ans tmp=t.query(t.root,1,n,id[top[x]],id[x]);
    273             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
    274             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
    275             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
    276             lastsum+=tmp.sum;
    277             ans=std::max(ans,lastsub);
    278             x=par[top[x]];
    279         }
    280         if(x!=y) {
    281             if(dep[x]<dep[y]) {
    282                 std::swap(x,y);
    283                 std::swap(lastsum,nextsum);
    284                 std::swap(lastsub,nextsub);
    285                 std::swap(lastpre,nextpre);
    286                 std::swap(lastsuf,nextsuf);
    287             }
    288             SegmentTree::Ans tmp=t.query(t.root,1,n,id[son[y]],id[x]);
    289             lastsub=std::max(std::max(lastsub,tmp.sub),lastpre+tmp.suf);
    290             lastpre=std::max(tmp.pre,lastpre+tmp.sum);
    291             lastsuf=std::max(lastsuf,lastsum+tmp.suf);
    292             lastsum+=tmp.sum;
    293         }
    294         ans=std::max(ans,std::max(lastsub,lastpre+nextpre));
    295         return ans;
    296     }
    297     if((id[y]-id[x]+cnt_cyc)%cnt_cyc>(id[x]-id[y]+cnt_cyc)%cnt_cyc) {
    298         std::swap(x,y);
    299         std::swap(lastsum,nextsum);
    300         std::swap(lastsub,nextsub);
    301         std::swap(lastpre,nextpre);
    302         std::swap(lastsuf,nextsuf);
    303     }
    304     SegmentTree::Ans tmp;
    305     if(id[x]<id[y]) {
    306         tmp=t.query(t.root,1,n,id[x],id[y]-1);
    307     } else {
    308         SegmentTree::Ans tmp1,tmp2;
    309         tmp1=t.query(t.root,1,n,id[x],cnt_cyc);
    310         if(id[y]!=1) tmp2=t.query(t.root,1,n,1,id[y]-1);
    311         if(id[y]!=1) {
    312             tmp.sum=tmp1.sum+tmp2.sum;
    313             tmp.sub=std::max(std::max(tmp1.sub,tmp2.sub),tmp1.suf+tmp2.pre);
    314             tmp.pre=std::max(tmp1.pre,tmp1.sum+tmp2.pre);
    315             tmp.suf=std::max(tmp2.suf,tmp2.sum+tmp1.suf);
    316         } else {
    317             tmp=tmp1;
    318         }
    319     }
    320     ans=std::max(ans,tmp.sub);
    321     ans=std::max(ans,lastpre+tmp.pre);
    322     ans=std::max(ans,nextpre+tmp.suf);
    323     ans=std::max(ans,lastpre+nextpre+tmp.sum);
    324     return ans;
    325 }
    326 int main() {
    327     n=getint();
    328     for(int i=1;i<=n;i++) {
    329         int u=getint(),v=getint(),w=getint();
    330         add_edge(u,v,w);
    331         add_edge(v,u,w);
    332     }
    333     dfs1(1,0);
    334     for(rt=1;rt<=cnt_cyc;rt++) {
    335         if(rt==cnt_cyc) dfs3(cyc[rt],0);
    336         dfs2(cyc[rt]);
    337     }
    338     t.build(t.root,1,n);
    339     for(int m=getint();m;m--) {
    340         char op[2];
    341         scanf("%1s",op);
    342         switch(op[0]) {
    343             case 'f': {
    344                 int x=getint(),y=getint();
    345                 modify(x,y);
    346                 break;
    347             }
    348             case '?': {
    349                 int x=getint(),y=getint();
    350                 printf("%lld
    ",query(x,y));
    351                 break;
    352             }
    353         }
    354     }
    355     return 0;
    356 }

     附数据生成器:

     1 #include<ctime>
     2 #include<vector>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 const int V=100001;
     6 std::vector<int> e[V];
     7 inline void add_edge(const int u,const int v) {
     8     e[u].push_back(v);
     9 }
    10 int par[V],dep[V],top[V],son[V],size[V];
    11 void dfs1(const int x) {
    12     size[x]=1;
    13     dep[x]=dep[par[x]]+1;
    14     for(unsigned i=0;i<e[x].size();i++) {
    15         int &y=e[x][i];
    16         dfs1(y);
    17         size[x]+=size[y];
    18         if(size[y]>size[son[x]]) son[x]=y;
    19     }
    20 }
    21 void dfs2(const int x) {
    22     top[x]=x==son[par[x]]?top[par[x]]:x;
    23     for(unsigned i=0;i<e[x].size();i++) {
    24         int &y=e[x][i];
    25         dfs2(y);
    26     }
    27 }
    28 inline int get_lca(int x,int y) {
    29     while(top[x]!=top[y]) {
    30         if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    31         x=par[top[x]];
    32     }
    33     if(dep[x]<dep[y]) std::swap(x,y);
    34     return y;
    35 }
    36 int main() {
    37     srand(time(NULL));
    38     int n=100000,m=100000,w=20001;
    39     printf("%d
    ",n);
    40     for(int i=2;i<=n;i++) {
    41         printf("%d %d %d
    ",par[i]=rand()%(i-1)+1,i,rand()%w-w/2);
    42         add_edge(par[i],i);
    43     }
    44     dfs1(1);
    45     dfs2(1);
    46     for(int i=1;i<n;i++) {
    47         if(i!=par[n]) {
    48             int lca=get_lca(i,n);
    49             if((dep[i]+dep[n]-dep[lca]*2)&1) continue;
    50             printf("%d %d %d
    ",i,n,rand()%w-w/2);
    51             break;
    52         }
    53     }
    54     printf("%d
    ",m);
    55     for(int i=1;i<=m;i++) {
    56         int op=rand()%2;
    57         if(op) {
    58             int y=rand()%(n-2)+2;
    59             int x=rand()%(y-1)+1;
    60             printf("? %d %d
    ",x,y);
    61         } else {
    62             int y=rand()%(n-2)+2;
    63             int x=rand()%(y-1)+1;
    64             printf("f %d %d
    ",x,y);
    65         }
    66     }
    67     return 0;
    68 }
    View Code
  • 相关阅读:
    POJ 1887 Testing the CATCHER
    HDU 3374 String Problem
    HDU 2609 How many
    POJ 1509 Glass Beads
    POJ 1458 Common Subsequence
    POJ 1159 Palindrome
    POJ 1056 IMMEDIATE DECODABILITY
    POJ 3080 Blue Jeans
    POJ 1200 Crazy Search
    软件体系结构的艺术阅读笔记1
  • 原文地址:https://www.cnblogs.com/skylee03/p/7506331.html
Copyright © 2011-2022 走看看