码迷,mamicode.com
首页 > 其他好文 > 详细

QTree1 【题解】

时间:2019-05-02 09:21:04      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:scanf   namespace   记录   spoj   双向   数组   line   ret   +=   

题目背景

数据规模和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之间边权最大值

输入样例:

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

输出样例:

1
3

解:

    本题相较于洛谷P1505相比,操作少了许多。但是,两者单点修改有区别。此题要求修改第i条边,所以要开一个数组记录边所指向的点,而且注意,由于之前建的是双向边,所以记时i要除以二,修改时修改id[back[x]].

    代码:

 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#define MAXN 200010
#define inf 0x7fffffff
using namespace std;
struct node{
    int nxt,to;
}e[MAXN<<1];
int head[MAXN],son[MAXN],top[MAXN],dep[MAXN];
int n,m,siz[MAXN],f[MAXN],a[MAXN],val[MAXN],xh;
int cnt,tot,id[MAXN],rk[MAXN],dt,rt,back[MAXN];
inline void swap(int &x,int &y){x^=y^=x^=y;}
char s[10];
inline int max_(int a,int b){return a>b?a:b;}
inline int min_(int a,int b){return a<b?a:b;}
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<0||ch>9){
        if(ch==-)w=-1;
        ch=getchar();
    }while(ch>=0&&ch<=9){
        s=(s<<1)+(s<<3)+(ch^48);
        ch=getchar();
    }return s*w;
}
struct Node{
    int ls,rs,sum,tag,maxn,minn,l,r;
}tr[MAXN<<2];
inline void add(int x,int y,int w){
    e[++tot].to=y;
    e[tot].nxt=head[x];
    head[x]=tot;
    a[tot]=w;
}void dfs1(int u){
    siz[u]=1;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==f[u])continue;
        if(i%2==0)back[i/2]=v;
        else back[i/2+1]=v;
        f[v]=u;
        val[v]=a[i];
        dep[v]=dep[u]+1;
        dfs1(v);
        siz[u]=siz[v]+1;
        if(siz[son[u]]<siz[v])son[u]=v;
    }
}void dfs2(int u,int t){
    top[u]=t;
    rk[id[u]=++dt]=u;
    if(!son[u])return;
    dfs2(son[u],t);
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v!=f[u]&&v!=son[u])dfs2(v,v);
    }
}
#define lc tr[x].ls
#define rc tr[x].rs
inline void pushup(int x){
    //tr[x].sum=tr[lc].sum+tr[rc].sum;
    tr[x].maxn=max_(tr[lc].maxn,tr[rc].maxn);
    //tr[x].minn=min_(tr[lc].minn,tr[rc].minn);
}
inline void pushdown(int x){
    if(tr[x].tag){
        tr[lc].sum=-tr[lc].sum,tr[lc].tag^=1;
        tr[rc].sum=-tr[rc].sum,tr[rc].tag^=1;
        int x1=tr[lc].maxn,y1=tr[lc].minn;
        int x2=tr[rc].maxn,y2=tr[rc].minn;
        tr[lc].maxn=-y1,tr[lc].minn=-x1;
        tr[rc].maxn=-y2,tr[rc].minn=-x2;
        tr[x].tag=0;
    }
}
void build(int li,int ri,int &x){
    x=++cnt;
    tr[x].l=li;tr[x].r=ri;
    if(li==ri){
        tr[x].minn=tr[x].maxn=tr[x].sum=val[rk[li]];
        return;
    }int mid=(li+ri)>>1;
    build(li,mid,lc);
    build(mid+1,ri,rc);
    pushup(x);
}
void change(int x,int val,int cur){
    if(tr[x].l==tr[x].r){
        tr[x].sum=tr[x].maxn=tr[x].minn=val;
        return;
    }//pushdown(x);
    int mid=(tr[x].l+tr[x].r)>>1;
    if(cur<=mid)change(lc,val,cur);
    else change(rc,val,cur);
    pushup(x);
}
void modify(int li,int ri,int x){
    if(tr[x].l>=li&&tr[x].r<=ri){
        tr[x].sum=-tr[x].sum,tr[x].tag^=1;
        int x1=tr[x].maxn,y1=tr[x].minn;
        tr[x].maxn=-y1,tr[x].minn=-x1;
        return;
    }pushdown(x);
    int mid=(tr[x].l+tr[x].r)>>1;
    if(li<=mid)modify(li,ri,lc);
    if(mid<ri)modify(li,ri,rc);
    pushup(x);
}
int query_s(int li,int ri,int x){
    if(tr[x].l>ri||tr[x].r<li)return 0;
    if(tr[x].l>=li&&tr[x].r<=ri)return tr[x].sum;
    pushdown(x);
    int mid=(tr[x].l+tr[x].r)>>1,ans=0;
    ans=query_s(li,ri,lc)+query_s(li,ri,rc);
    return ans;
}
int query_x(int li,int ri,int x){
    if(tr[x].l>=li&&tr[x].r<=ri)return tr[x].maxn;
    pushdown(x);
    int mid=(tr[x].l+tr[x].r)>>1,ans=-inf;
    if(li<=mid)ans=max_(ans,query_x(li,ri,lc));
    if(mid<ri)ans=max_(ans,query_x(li,ri,rc));
    return ans;
}
int query_n(int li,int ri,int x){
    if(tr[x].l>=li&&tr[x].r<=ri){return tr[x].minn;}
    pushdown(x);int mid=(tr[x].l+tr[x].r)>>1,ans=inf;
    if(li<=mid)ans=min_(ans,query_n(li,ri,lc));
    if(mid<ri)ans=min_(ans,query_n(li,ri,rc));
    return ans;
}
void Segment_change(int x,int y){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
        modify(id[fx],id[x],rt);
        x=f[fx],fx=top[x];
    }if(id[x]>id[y])swap(x,y);
    modify(id[x]+1,id[y],rt);
}
int query(int x,int y,int ck){//ck 0sum 1max 2min
    int fx=top[x],fy=top[y],ans;
    if(ck==0)ans=0;else if(ck==1)ans=-inf;else ans=inf;
    while(fx!=fy){
        if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
        if(ck==0)ans+=query_s(id[fx],id[x],rt);
        else if(ck==1)ans=max_(ans,query_x(id[fx],id[x],rt));
        else if(ck==2)ans=min_(ans,query_n(id[fx],id[x],rt));
        x=f[fx],fx=top[x];
    }if(id[x]>id[y])swap(x,y);
    if(ck==0)ans+=query_s(id[x]+1,id[y],rt);
    else if(ck==1)ans=max_(ans,query_x(id[x]+1,id[y],rt));
    else if(ck==2)ans=min_(ans,query_n(id[x]+1,id[y],rt));
    return ans;
}
int main(){dep[0]=1;
    n=read();
    for(register int i=1;i<n;++i){
        int u=read(),v=read(),w=read();
        add(u,v,w);add(v,u,w);
    }dfs1(1);
    dfs2(1,1);
    build(1,n,rt);
    while(1){
        scanf("%s",s);
        if(s[0]==D)break;
        int x=read(),y=read(); 
        if(s[0]==C)change(rt,y,id[back[x]]);
        else if(s[0]==Q){
            if(x==y)printf("0\n");
            else printf("%d\n",query(x,y,1));
        }
    }
    return 0;
}

 

感谢fsq dalao指教。

 

QTree1 【题解】

标签:scanf   namespace   记录   spoj   双向   数组   line   ret   +=   

原文地址:https://www.cnblogs.com/h-lka/p/10801550.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!