zoukankan      html  css  js  c++  java
  • bzoj 2959 长跑(LCT+BCC+并查集)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2959

    【题意】

        n个点,提供操作:连边,修改点权,查询自定义边的方向后起点a终点b能经过的最大点权和。

    【思路】

        对于一个边的双连通分量,显然可以将权值全部获得。

        如果没有连边操作,我们只需要将一个bcc缩点后求得a->b路径上的点权和即可。

        加上连边后,使用并查集代表一个bcc,如果u,v之间不连通直接连边,如果已经连通则构成一个bcc,使用并查集将LCT的所有节点合并。

        注意缩点后以并查集的代表元为该点,Access上找父亲的时候应该用父亲的bcc代表元。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     10 using namespace std;
     11 
     12 typedef long long ll;
     13 const int N = 3e5+10;
     14 
     15 ll read() {
     16     char c=getchar();
     17     ll f=1,x=0;
     18     while(!isdigit(c)) {
     19         if(c=='-') f=-1; c=getchar();
     20     }
     21     while(isdigit(c))
     22         x=x*10+c-'0',c=getchar();
     23     return x*f;
     24 }
     25 
     26 struct UFS {
     27     int p[N];
     28     int ifind(int x) {
     29         if(p[x]==0||x==p[x]) return p[x]=x;
     30         return p[x]=ifind(p[x]); 
     31     }
     32     void iunion(int x,int y) {
     33         x=ifind(x),y=ifind(y);
     34         if(x!=y) p[x]=y;
     35     }
     36 } bcc,S;
     37 
     38 namespace LCT {
     39 
     40     struct Node {
     41         Node *ch[2],*fa;
     42         int v,rev,sum;
     43         Node() {}
     44         Node(int x) ;
     45         void reverse() {
     46             rev^=1;
     47             swap(ch[0],ch[1]);
     48         }
     49         void up_push() {
     50             if(fa->ch[0]==this||fa->ch[1]==this) 
     51                 fa->up_push();
     52             if(rev) {
     53                 ch[0]->reverse();
     54                 ch[1]->reverse();
     55                 rev=0;
     56             }
     57         }
     58         void maintain() {
     59             sum=v+ch[0]->sum+ch[1]->sum;
     60         }
     61     } T[N],*null=&T[0];
     62     Node::Node(int x) {
     63         rev=0;
     64         v=sum=x;
     65         ch[0]=ch[1]=fa=null;
     66     }
     67     
     68     void rot(Node* o,int d) {
     69         Node *p=o->fa;
     70         p->ch[d]=o->ch[d^1];
     71         o->ch[d^1]->fa=p;
     72         o->ch[d^1]=p;
     73         o->fa=p->fa;
     74         if(p==p->fa->ch[0])
     75             p->fa->ch[0]=o;
     76         else if(p==p->fa->ch[1])
     77             p->fa->ch[1]=o;
     78         p->fa=o;
     79         p->maintain();
     80     }
     81     void splay(Node *o) {
     82         o->up_push();
     83         Node *nf,*nff;
     84         while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
     85             nf=o->fa,nff=nf->fa;
     86             if(o==nf->ch[0]) {
     87                 if(nf==nff->ch[0]) rot(nf,0);
     88                 rot(o,0);
     89             } else {
     90                 if(nf==nff->ch[1]) rot(nf,1);
     91                 rot(o,1);
     92             }
     93         }
     94         o->maintain();
     95     }
     96     void Access(Node *o) {
     97         Node *son=null;
     98         while(o!=null) {
     99             splay(o);
    100             o->ch[1]=son;
    101             o->maintain();
    102             o->fa=&T[bcc.ifind(o->fa-T)];
    103             son=o; o=o->fa;
    104         }
    105     }
    106     void evert(Node *o) {
    107         Access(o); 
    108         splay(o);
    109         o->reverse();
    110     }
    111     void Link(Node *u, Node *v) {
    112         evert(u);
    113         u->fa=v;
    114     }
    115 
    116 }
    117 
    118 using namespace LCT;
    119 
    120 int n,m,a[N];
    121 
    122 void merge(Node* &u,Node* v) 
    123 {
    124     if(u==null) return ;
    125     v->v+=u->v;
    126     bcc.iunion(u-T,v-T);
    127     merge(u->ch[0],v);
    128     merge(u->ch[1],v);
    129     u=null;
    130 }
    131 
    132 int main()
    133 {
    134     n=read(),m=read();
    135     FOR(i,1,n) {
    136         a[i]=read(); T[i]=Node(a[i]);
    137     }
    138     int op,u,v;
    139     FOR(i,1,m) {
    140         op=read(),u=read(),v=read();
    141         if(op==1) {
    142             u=bcc.ifind(u),v=bcc.ifind(v);
    143             if(u==v) continue;
    144             if(S.ifind(u)!=S.ifind(v))
    145                 Link(&T[u],&T[v]),
    146                 S.iunion(u,v);
    147             else {
    148                 evert(&T[u]);
    149                 Access(&T[v]),splay(&T[v]);
    150                 merge(T[v].ch[0],&T[v]);
    151                 merge(T[v].ch[1],&T[v]);
    152                 T[v].maintain();
    153             }
    154         } else 
    155         if(op==2) {
    156             splay(&T[bcc.ifind(u)]);
    157             T[bcc.ifind(u)].v+=v-a[u];
    158             T[bcc.ifind(u)].maintain();
    159             a[u]=v;
    160         } else {
    161             u=bcc.ifind(u),v=bcc.ifind(v);
    162             if(S.ifind(u)!=S.ifind(v)) puts("-1");
    163             else {
    164                 evert(&T[u]);
    165                 Access(&T[v]),splay(&T[v]);
    166                 printf("%d
    ",T[v].sum);
    167             }
    168         }
    169     }
    170     return 0;
    171 }

    Q:打码的最怕什么

    A:手残和眼瞎。

    真不巧,我两样都是

  • 相关阅读:
    高中信息技术《算法与程序设计VB(选修)》知识要点
    信息技术选修一总结
    文学给人以相爱的力量
    雾霾
    杯子
    递归
    死锁
    高精度计算练习1
    高精度加法的优化
    字符串函数与过程
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5323664.html
Copyright © 2011-2022 走看看