洛谷P4114 Qtree1

題目背景

數據規模和spoj上有所不同

題目描述

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

  • CHANGE i ti 把第i條邊的邊權變成ti

  • QUERY a b 輸出從a到b的路徑中最大的邊權,當a=b的時候,輸出0

輸入輸出格式

輸入格式:

第一行輸入一個n,表示節點個數

第二行到第n行每行輸入三個數,ui,vi,wi,分別表示 ui,vi有一條邊,邊權是wi

第n+1行開始,一共有不定數量行,每一行分別有以下三種可能

CHANGE,QUERY同題意所述

DONE表示輸入結束

輸出格式:

對於每個QUERY操作,輸出一個數,表示a b之間邊權最大值

輸入輸出樣例

輸入樣例#1: 
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
輸出樣例#1: 
1
3

說明

數據保證:

\leq n \leq 10^5105

操作次數 \leq 3*10^53105

wi和ti \leq 2^{31}-12311

樹鏈剖分+線段樹。

模板水題不解釋。。。

附代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) b[x].data
#define LSIDE(x) b[x].l
#define RSIDE(x) b[x].r
#define MAXN 100010
using namespace std;
int n,m,c=1,d=1;
int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
struct node1{
    int next,to,w;
}a[MAXN<<1];
struct node2{
    int data,l,r;
}b[MAXN<<2];
struct node3{
    int u,v,w;
}g[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline void add(int u,int v,int w){
    a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    a[c].to=u;a[c].w=w;a[c].next=head[v];head[v]=c++;
}
void dfs1(int rt){
    son[rt]=0;size[rt]=1;
    for(int i=head[rt];i;i=a[i].next){
        int will=a[i].to;
        if(!deep[will]){
            deep[will]=deep[rt]+1;
            fa[will]=rt;
            dfs1(will);
            size[rt]+=size[will];
            if(size[son[rt]]<size[will])son[rt]=will;
        }
    }
}
void dfs2(int rt,int f){
    id[rt]=d++;top[rt]=f;
    if(son[rt])dfs2(son[rt],f);
    for(int i=head[rt];i;i=a[i].next){
        int will=a[i].to;
        if(will!=fa[rt]&&will!=son[rt])
        dfs2(will,will);
    }
}
inline void pushup(int rt){
    DATA(rt)=max(DATA(LSON),DATA(RSON));
}
void buildtree(int l,int r,int rt){
    int mid;
    LSIDE(rt)=l;
    RSIDE(rt)=r;
    if(l==r){
        DATA(rt)=0;
        return;
    }
    mid=l+r>>1;
    buildtree(l,mid,LSON);
    buildtree(mid+1,r,RSON);
    pushup(rt);
}
void update(int l,int r,int c,int rt){
    int mid;
    if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
        DATA(rt)=c;
        return;
    }
    mid=LSIDE(rt)+RSIDE(rt)>>1;
    if(l<=mid)update(l,r,c,LSON);
    if(mid<r)update(l,r,c,RSON);
    pushup(rt);
}
int query(int l,int r,int rt){
    int mid,ans=0;
    if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
    mid=LSIDE(rt)+RSIDE(rt)>>1;
    if(l<=mid)ans=max(ans,query(l,r,LSON));
    if(mid<r)ans=max(ans,query(l,r,RSON));
    return ans;
}
void get_max(int x,int y){
    int s=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]])swap(x,y);
        s=max(s,query(id[top[x]],id[x],1));
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])swap(x,y);
    if(x!=y)s=max(s,query(id[x]+1,id[y],1));
    printf("%d\n",s);
    return;
}
void work(){
    char ch[10];
    int x,y;
    while(1){
        scanf("%s",ch);
        if(ch[0]=='D')return;
        x=read();y=read();
        if(ch[0]=='C'){
            g[x].w=y;
            update(id[g[x].v],id[g[x].v],y,1);
        }
        if(ch[0]=='Q'){
            if(x==y)printf("0\n");
            else get_max(x,y);
        }
    }
}
void init(){
    n=read();
    for(int i=1;i<n;i++){
        g[i].u=read();g[i].v=read();g[i].w=read();
        add(g[i].u,g[i].v,g[i].w);
    }
    deep[1]=1;
    dfs1(1);
    dfs2(1,1);
    buildtree(1,n,1);
    for(int i=1;i<n;i++){
        if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v);
        update(id[g[i].v],id[g[i].v],g[i].w,1);
    }
}
int main(){
    init();
    work();
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章