bzoj2594 [Wc2006]水管局长数据加强版 离线+LCT维护边权

LCT维护边权势把每条边都当成一个点赋予点权,原来的点当然也保留,如果求和点权赋为0,求max点权赋为-INF,如果都要求,那就弄两三个点权。

需要注意的是,LCT的link操作必须换根,如果不把x设为根而直接pre[x]=y的话,结果并不是连接x和y而是连接x的splay的根和y。在弹飞绵羊的题中之所以不用换根是因为x本来就是根。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1500100;
const int INF=1e9+10;

int getint()
{
    char ch=getchar();
    for(;ch>'9'||ch<'0';ch=getchar());
    int tmp=0;
    for(;'0'<=ch&&ch<='9';ch=getchar())
    tmp=tmp*10+int(ch)-48;
    return tmp;
}

int n,m,qn;
struct Edge
{
    int u,v,w;
    bool e;
    friend bool operator<(Edge A,Edge B)
    {
        return A.u==B.u?A.v<B.v:A.u<B.u;
    }
};Edge e[maxn];
struct Query
{
    int op,x,y;
};Query q[maxn];
int pre[maxn],ch[maxn][2],rev[maxn];
struct Node
{
    int w,id;
    friend bool operator<(Node A,Node B)
    {
        return A.w<B.w;
    }
};Node val[maxn],Max[maxn];
int fa[maxn];
int u,v,w;
int op,x,y;
int ans[maxn],cnt;

bool cmp(Edge A,Edge B)
{
    return A.w<B.w;
}

int bin(int l,int r,int x,int y)
{
    int res=l;
    while(l<=r){
        int m=(l+r)>>1;
        if(e[m].u==x&&e[m].v==y) return m;
        if(x>e[m].u||(x==e[m].u&&y>e[m].v)) l=m+1;
        else r=m-1;
    }
}

int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

bool isroot(int x)
{
    return ch[pre[x]][0]!=x&&ch[pre[x]][1]!=x;
}

void update_rev(int x)
{
    if(!x) return;
    swap(ch[x][0],ch[x][1]);
    rev[x]^=1;
}

void up(int x)
{
    Max[x]=max(val[x],max(Max[ch[x][0]],Max[ch[x][1]]));
}

void down(int x)
{
    if(rev[x]){
        update_rev(ch[x][0]);
        update_rev(ch[x][1]);
        rev[x]=0;
    }
}

void Pd(int x)
{
    if(!isroot(x)) Pd(pre[x]);
    down(x);
}

void rot(int x,int kind)
{
    int y=pre[x];
    ch[y][kind^1]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if(!isroot(y)) ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    ch[x][kind]=y;
    pre[y]=x;
    up(y);
}

void splay(int x)
{
    Pd(x);
    while(!isroot(x)){
        if(isroot(pre[x])) rot(x,ch[pre[x]][0]==x);
        else{
            int y=pre[x],z=pre[y];
            int kind=ch[y][0]==x,one=0;
            if(ch[y][0]==x&&ch[z][0]==y) one=1;
            if(ch[y][1]==x&&ch[z][1]==y) one=1;
            if(one) rot(y,kind),rot(x,kind);
            else rot(x,kind),rot(x,kind^1);
        }
    }
    up(x);
}

int access(int x)
{
    int t=0;
    while(x){
        splay(x);
        ch[x][1]=t;
        t=x;x=pre[x];
        up(t);
    }
    return t;
}

void makeroot(int x)
{
    access(x);
    splay(x);
    update_rev(x);
}

void link(int x,int y)
{
    makeroot(x);
    pre[x]=y;
}

void cut(int x,int y)
{
    makeroot(x);
    access(y);
    splay(y);
    ch[y][0]=pre[x]=0;
}

Node query(int x,int y)
{
    makeroot(x);
    access(y);
    splay(y);
    return Max[y];
}

int main()
{
    freopen("in.txt","r",stdin);
    while(~scanf("%d%d%d",&n,&m,&qn)){
        REP(i,1,n) fa[i]=i;
        REP(i,1,m){
            u=getint();v=getint();w=getint();
            if(u>v) swap(u,v);
            e[i]={u,v,w,1};
        }
        sort(e+1,e+m+1);
        REP(i,1,qn){
            op=getint();x=getint();y=getint();
            if(x>y) swap(x,y);
            q[i]={op,x,y};
            if(op==2){
                int k=bin(1,m,x,y);
                e[k].e=0;
            }
        }
        sort(e+1,e+m+1,cmp);
        REP(i,1,m){
            if(e[i].e==0) continue;
            x=find(e[i].u),y=find(e[i].v);
            if(x==y) e[i].e=0;
            else fa[x]=y;
        }
        sort(e+1,e+m+1);
        REP(i,0,n+m) pre[i]=rev[i]=0,MS0(ch[i]),val[i]={-INF,i},Max[i]={-INF,i};
        REP(i,1,m){
            if(e[i].e==0) continue;
            x=e[i].u,y=e[i].v,w=e[i].w;
            val[n+i].w=Max[n+i].w=w;
            link(x,n+i);
            link(y,n+i);
        }
        Node tmp;int xx,yy;cnt=0;
        for(int i=qn;i>=1;i--){
            op=q[i].op,x=q[i].x,y=q[i].y;
            tmp=query(x,y);
            if(op==1) ans[++cnt]=tmp.w;
            else{
                int k=bin(1,m,x,y);
                if(e[k].w<tmp.w){
                    xx=e[tmp.id-n].u,yy=e[tmp.id-n].v;
                    cut(tmp.id,xx);
                    cut(tmp.id,yy);
                    pre[n+k]=rev[n+k]=0;MS0(ch[n+k]);
                    val[n+k]=Max[n+k]={e[k].w,n+k};
                    link(x,n+k);
                    link(y,n+k);
                }
            }
        }
        for(int i=cnt;i>=1;i--) printf("%d\n",ans[i]);
    }
    return 0;
}
View Code

 

没有AC不了的题,只有不努力的ACMER!
posted @ 2016-03-02 13:31  __560  阅读(197)  评论(0编辑  收藏  举报