1. 程式人生 > >樹鏈剖分【洛谷P4114】 Qtree1

樹鏈剖分【洛谷P4114】 Qtree1

read getc n) != str etc upd %s pri

P4114 Qtree1

題目描述

給定一棵n個節點的樹,有兩個操作:

  • CHANGE i ti 把第i條邊的邊權變成ti
  • QUERY a b 輸出從a到b的路徑中最大的邊權,當a=b的時候,輸出0

碼農題。

話說我碼得變快了啊,雖然跟顧z吹45分鐘碼完Qtree沒有完成,不過總共用了55分鐘還是不長的嘿嘿。

code:

#include <iostream>
#include <cstdio>

#define ls(o) o<<1
#define rs(o) o<<1|1

#define int long long

using namespace std;

const int wx=500017;

int head[wx],dfn[wx],size[wx],f[wx][23],dis[wx][23],dep[wx];
int son[wx],a[wx],top[wx],tid[wx];
int n,num,tot;
char opt[17];

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

/*~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~*/

struct e{
    int nxt,to,dis;
}edge[wx*2];

void add(int from,int to,int dis){
    edge[++num].nxt=head[from];
    edge[num].to=to;
    edge[num].dis=dis;
    head[from]=num;
}

int first_dfs(int u,int fa){
    size[u]=1; int maxson=-1; dep[u]=dep[fa]+1;
    dis[u][0]=a[u];
    f[u][0]=fa;
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==fa)continue;
        a[v]=edge[i].dis;
        first_dfs(v,u);
        size[u]+=size[v];
        if(size[v]>maxson){
            maxson=size[v]; son[u]=v;
        }
    }
}

int second_dfs(int u,int topf){
    dfn[u]=++tot; top[u]=topf; tid[tot]=u;
    if(son[u])second_dfs(son[u],topf);
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(dfn[v]||v==f[u][0])continue;
        second_dfs(v,v);
    }
}
/*~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~*/


/*~~~~~~~~~~~~~~~~~ SGT~~~~~~~~~~~~~~~~~~~~~*/

struct SGT{
    int l,r,tag,ma;
    #define tag(o) t[o].tag
    #define ma(o) t[o].ma
}t[wx*4];

void up(int o){
    ma(o)=max(ma(ls(o)),ma(rs(o)));
} 

void down(int o){
    if(tag(o)!=-1){
        ma(ls(o))=tag(o); ma(rs(o))=tag(o);
        tag(ls(o))=tag(o); tag(rs(o))=tag(o);
        tag(o)=-1;
    }
}

void build(int o,int l,int r){
    t[o].l=l; t[o].r=r; tag(o)=-1;
    if(l==r){ma(o)=a[tid[l]]; return ;}
    int mid=t[o].l+t[o].r>>1;
    if(l<=mid)build(ls(o),l,mid);
    if(r>mid)build(rs(o),mid+1,r);
    up(o);
}

void update_SGT(int o,int l,int r,int k){
    if(l<=t[o].l&&t[o].r<=r){
        ma(o)=k; tag(o)=k;
        return ;
    }
    down(o);
    int mid=t[o].l+t[o].r>>1;
    if(l<=mid)update_SGT(ls(o),l,r,k);
    if(r>mid)update_SGT(rs(o),l,r,k);
    up(o);
}

int query_SGT(int o,int l,int r){
    if(l>r)return 0;
    if(l<=t[o].l&&t[o].r<=r){
        return ma(o);
    }
    down(o); int maxn=-1;
    int mid=t[o].l+t[o].r>>1;
    if(l<=mid)maxn=max(maxn,query_SGT(ls(o),l,r));
    if(r>mid)maxn=max(maxn,query_SGT(rs(o),l,r));
    return maxn;
}

/*~~~~~~~~~~~~~~~~~ SGT~~~~~~~~~~~~~~~~~~~~~*/

/*~~~~~~~~~~~~~~~~~ LCA~~~~~~~~~~~~~~~~~~~~~*/

void pre(){
    for(int j=1;j<=21;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1],dis[i][j]=max(dis[f[i][j-1]][j-1],dis[i][j-1]);
}

int find(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    int re=-1;
    for(int i=21;i>=0;i--){
        if(dep[f[x][i]]>=dep[y]){
            re=max(re,dis[x][i]);
            x=f[x][i];
        }
    }
    if(x==y)return re;
    for(int i=21;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            re=max(re,max(dis[x][i],dis[y][i]));
            x=f[x][i]; y=f[y][i];
        }
    }
    return max(re,max(dis[x][0],dis[y][0]));
}

int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=21;i>=0;i--){
        if(dep[f[x][i]]>=dep[y]){
            x=f[x][i];
        }
    }
    if(x==y)return x;
    for(int i=21;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            x=f[x][i]; y=f[y][i];
        }
    }
    return f[x][0];
}

/*~~~~~~~~~~~~~~~~~ LCA~~~~~~~~~~~~~~~~~~~~~*/

/*~~~~~~~~~~~~~~~~~ shu pou~~~~~~~~~~~~~~~~~*/

void update(int x,int y,int k){
    int fx=top[x]; int fy=top[y];
    while(fx!=fy){
        if(dep[fx]>=dep[fy])update_SGT(1,dfn[fx],dfn[x],k),x=f[fx][0];
        else update_SGT(1,dfn[fy],dfn[y],k),y=f[fy][0];
        fx=top[x]; fy=top[y];
    }
    if(dfn[x]>dfn[y])swap(x,y);
    update_SGT(1,dfn[x],dfn[y],k);
}

int query(int x,int y){
    int fx=top[x]; int fy=top[y]; int re=-1;
    while(fx!=fy){
        if(dep[fx]>=dep[fy])re=max(re,query_SGT(1,dfn[fx],dfn[x])),x=f[fx][0];
        else re=max(re,query_SGT(1,dfn[fy],dfn[y])),y=f[fy][0];
        fx=top[x]; fy=top[y];
    }
    if(dfn[x]>dfn[y])swap(x,y);
    re=max(re,query_SGT(1,dfn[x],dfn[y]));
    return re;
}

/*~~~~~~~~~~~~~~~~~ shu pou~~~~~~~~~~~~~~~~~*/
signed main(){
    n=read();
    for(int i=1;i<n;i++){
        int x,y,z;
        x=read(); y=read(); z=read();
        add(x,y,z); add(y,x,z);
    }
    first_dfs(1,0); second_dfs(1,1); build(1,1,n); pre();
    while(1){
        scanf("%s",opt+1);
        if(opt[1]=='D')break;
        if(opt[1]=='Q'){
            int x,y;
            x=read(); y=read();
            if(x==y)puts("0");
            else{   
                int lca=LCA(x,y);
                int tmp=query_SGT(1,dfn[lca],dfn[lca]);
                update_SGT(1,dfn[lca],dfn[lca],-521);
                printf("%lld\n",query(x,y));
                update_SGT(1,dfn[lca],dfn[lca],tmp);
            }
        }
        if(opt[1]=='C'){
            int x,y;
            x=read(); y=read();
            int x1=edge[x*2-1].to;
            int x2=edge[x*2].to;
            if(dep[x1]>dep[x2])x=x1;
            else x=x2;
            update(x,x,y);
        }
    }
    return 0;
}

/*

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

*/

樹鏈剖分【洛谷P4114】 Qtree1