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
  • 相关阅读:
    查看某个存储过程
    qemu-libvirt-kvm三者之间的关系
    gitlab安装
    jenkins安装
    数据库迁移(分享十一续集)
    数据库迁移(分享十一续集)
    数据库迁移(分享十一续集)
    数据库迁移(分享十一)
    云上迁移(分享十)
    阿里云迁移(分享九)
  • 原文地址:https://www.cnblogs.com/skylee03/p/7506331.html
Copyright © 2011-2022 走看看