zoukankan      html  css  js  c++  java
  • [BZOJ]2959: 长跑

    题解:   我们考虑一条链时 答案为链上和  路径上有环时  这个环上的点都会产生贡献  然后我们可以 用并查集来维护LCT  有环时直接缩成一个点即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=3e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    
    int res[MAXN],pre[MAXN],ch[MAXN][2],key[MAXN],sum[MAXN];
    int f[MAXN];
    bool rt[MAXN];
    
    int find1(int x){
        if(x==f[x])return x;
        return f[x]=find1(f[x]);
    }
    
    int a[MAXN];
    void newnode(int t){
        res[t]=pre[t]=ch[t][0]=ch[t][1]=0;key[t]=sum[t]=a[t];rt[t]=1;
    }
    
    void reverse(int x){
        if(!x)return ;
        swap(ch[x][0],ch[x][1]);
        res[x]^=1;
    }
    
    void push(int x){
        if(res[x]){
        reverse(ch[x][0]);
        reverse(ch[x][1]);
        res[x]^=1;
        }
    }
    
    void up(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];}
    
    void P(int x){
        if(!rt[x])P(find1(pre[x]));
        push(x);
    }
    
    
    void rotate(int x,int kind){
        int y=find1(pre[x]);
        ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
        if(rt[y])rt[y]=0,rt[x]=1;
        else ch[find1(pre[y])][ch[find1(pre[y])][1]==y]=x;
        pre[x]=find1(pre[y]);ch[x][kind]=y;pre[y]=x;
        up(y);
    }
    
    void splay(int x){
        P(x);
        while(!rt[x]){
        if(rt[find1(pre[x])])rotate(x,ch[find1(pre[x])][0]==x);
        else{
            int y=find1(pre[x]);int kind=ch[find1(pre[y])][0]==y;
            if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
            else rotate(y,kind),rotate(x,kind);
        }
        }
        up(x);
    }
    
    void access(int x){
        int y=0;
        while(x){
        splay(x);
        if(ch[x][1])rt[ch[x][1]]=1,pre[ch[x][1]]=x,ch[x][1]=0;
        if(rt[y])rt[y]=0;
        ch[x][1]=y;up(x);
        y=x;x=find1(pre[x]);
        }
    }
    
    bool pd(int u,int v){
        u=find1(u);v=find1(v);
        while(pre[u])u=find1(pre[u]);
        while(pre[v])v=find1(pre[v]);
        return u==v;
    }
    
    void mroot(int u){access(u);splay(u);reverse(u);}
    
    int st[MAXN],tot;
    
    void dfs(int x){
        if(!x)return ;
        st[++tot]=x;
        push(x);
        dfs(ch[x][0]);
        dfs(ch[x][1]);
    }
    
    void Tarjan(int u,int v){
        u=find1(u);v=find1(v);
        mroot(u);access(v);splay(v);
        tot=0;dfs(v);
        int ans=key[st[1]];
        //if(tot==1)cout<<"sb"<<endl;
        inc(i,2,tot){
        ans+=key[st[i]];
        int t1=find1(st[i-1]);
        int t2=find1(st[i]);
        if(t1==t2)continue;
        if(t1>t2)swap(t1,t2);
        f[t2]=t1;
        }
        inc(i,1,tot)rt[st[i]]=1,ch[st[i]][0]=ch[st[i]][1]=0,pre[st[i]]=0;
        key[find1(st[1])]=sum[find1(st[1])]=ans;
        splay(find1(st[1]));
        up(find1(st[1]));
    }
    
    void update(int x,int k){
        int t=find1(x);
        access(t);splay(t);key[t]+=(k-a[x]);
        a[x]=k;up(t);
    }
    
    void Link(int u,int v){
        u=find1(u);v=find1(v);
        mroot(u);mroot(v);
        pre[u]=v;
    }
    
    int query(int u,int v){
        if(!pd(u,v))return -1;
        int t1=find1(u);int t2=find1(v);
        if(t1==t2)return key[t1];
        mroot(t1);access(t2);splay(t2);
        return sum[t2];
    }
    
    int main(){
        int n=read();int m=read();
        inc(i,1,n)a[i]=read(),newnode(i),f[i]=i;
        int op,x,y;
        while(m--){
        op=read();x=read();y=read();
        if(op==1){
            if(find1(x)==find1(y))continue;
            if(pd(x,y))Tarjan(x,y);
            else Link(x,y);
        }
        else if(op==2)update(x,y);
        else printf("%d
    ",query(x,y));
        }
        return 0;
    }
    

      

    2959: 长跑

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1244  Solved: 614
    [Submit][Status][Discuss]

    Description

      某校开展了同学们喜闻乐见的阳光长跑活动。为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动。一时间操场上熙熙攘攘,摩肩接踵,盛况空前。
      为了让同学们更好地监督自己,学校推行了刷卡机制。
      学校中有n个地点,用1到n的整数表示,每个地点设有若干个刷卡机。
      有以下三类事件:
      1、修建了一条连接A地点和B地点的跑道。
      2、A点的刷卡机台数变为了B。
      3、进行了一次长跑。问一个同学从A出发,最后到达B最多可以刷卡多少次。具体的要求如下:
      当同学到达一个地点时,他可以在这里的每一台刷卡机上都刷卡。但每台刷卡机只能刷卡一次,即使多次到达同一地点也不能多次刷卡。
      为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。

    Input

      输入的第一行包含两个正整数n,m,表示地点的个数和操作的个数。
      第二行包含n个非负整数,其中第i个数为第个地点最开始刷卡机的台数。
      接下来有m行,每行包含三个非负整数P,A,B,P为事件类型,A,B为事件的两个参数。
      最初所有地点之间都没有跑道。
      每行相邻的两个数之间均用一个空格隔开。表示地点编号的数均在1到n之间,每个地点的刷卡机台数始终不超过10000,P=1,2,3。

    Output


      输出的行数等于第3类事件的个数,每行表示一个第3类事件。如果该情况下存在一种设定跑道方向的方案和路径的方案,可以到达,则输出最多可以刷卡的次数。如果A不能到达B,则输出-1。

    Sample Input

    9 31
    10 20 30 40 50 60 70 80 90
    3 1 2
    1 1 3
    1 1 2
    1 8 9
    1 2 4
    1 2 5
    1 4 6
    1 4 7
    3 1 8
    3 8 8
    1 8 9
    3 8 8
    3 7 5
    3 7 3
    1 4 1
    3 7 5
    3 7 3
    1 5 7
    3 6 5
    3 3 6
    1 2 4
    1 5 5
    3 3 6
    2 8 180
    3 8 8
    2 9 190
    3 9 9
    2 5 150
    3 3 6
    2 1 210
    3 3 6

    Sample Output


    -1
    -1
    80
    170
    180
    170
    190
    170
    250
    280
    280
    270
    370
    380
    580

    HINT

    数据规模及约定

      对于100%的数据,m<=5n,任意时刻,每个地点的刷卡机台数不超过10000。N<=1.5×105

  • 相关阅读:
    小程序入门
    页面滚动触底加载
    js取整
    【Codeforces 1389D】Segment Intersections
    【Codeforces 1385 E】Directing Edges
    【Codeforces 1369D】TediousLee
    【Codeforces Global Round 9 D】Replace by MEX
    【Codeforces Global Round 9 C】Element Extermination
    【Codeforces Round #639 (Div. 2) A】Puzzle Pieces
    【Codeforces Round #639 (Div. 2) B】Card Constructions
  • 原文地址:https://www.cnblogs.com/wang9897/p/10361996.html
Copyright © 2011-2022 走看看