[SDOI2014]旅行

Solution

挺简单的一道题,对每种颜色开一棵动态开点的线段树,然后树剖查询即可。

就当是复习一下树剖,然后规范一下写法。主要是记录一下代码。

#include<stdio.h>

const int N=1e5+7;

inline int read(){
    int x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

struct Node{
    Node(int ls_=0,int rs_=0,int mx_=0,int s_=0)
    :ls(ls_),rs(rs_),mx(mx_),s(s_){}
    int ls,rs,mx,s;
}t[N*20];

struct Init{
    int c,w;
}a[N];

struct E{
    int next,to;
}e[N<<1];

const int C=1e5;
int n,Q,in[N];
int head[N],sz[N],fa[N],son[N],top[N],dep[N];

inline int max(int x,int y){return x>y? x:y;}

inline void add(int id,int to){
    static int cnt=0;
    e[++cnt]=(E){head[id],to};
    head[id]=cnt;
}

void dfs(int u){
    sz[u]=1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[u]) continue;
        dep[v]=dep[u]+1,fa[v]=u;
        dfs(v),sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u]=v;
    }
}

void Dfs(int u,int tp){
    static int cnt=0;
    in[u]=++cnt,top[u]=tp;
    if(!son[u]) return ;
    Dfs(son[u],tp);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==son[u]||v==fa[u]) continue;
        Dfs(v,v);
    }
}

int W,pos;
void modify(int &id,int lf=1,int rf=n){
    static int cnt=C;
    if(!id) id=++cnt;
    if(lf==rf){t[id].s+=W,t[id].mx+=W;return;}
    int mid=(lf+rf)>>1;
    if(pos<=mid) modify(t[id].ls,lf,mid);
    else modify(t[id].rs,mid+1,rf);
    t[id].s=t[t[id].ls].s+t[t[id].rs].s;
    t[id].mx=max(t[t[id].ls].mx,t[t[id].rs].mx);
}

void merge(Node &x,const Node &y){
    x.mx=max(x.mx,y.mx);
    x.s+=y.s;
}

int L,R;
Node query(int id,int lf=1,int rf=n){
    if(!id) return (Node){0,0,0,0};
    if(L<=lf&&rf<=R) return t[id];
    int mid=(lf+rf)>>1; Node tmp;
    if(L<=mid) merge(tmp,query(t[id].ls,lf,mid));
    if(R>mid) merge(tmp,query(t[id].rs,mid+1,rf));
    return tmp;
}

inline void swap(int &x,int &y){x^=y,y^=x,x^=y;}
Node Query(int u,int v){
    Node ans; int rt=a[u].c;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        L=in[top[u]],R=in[u];
        merge(ans,query(rt));
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    L=in[v],R=in[u],merge(ans,query(rt));
    return ans;
}

int main(){
    n=read(),Q=read();
    for(int i=1;i<=n;i++)
        a[i].w=read(),a[i].c=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    dep[1]=1,dfs(1),Dfs(1,1);
    for(int i=1;i<=n;i++)
        W=a[i].w,pos=in[i],modify(a[i].c);
    char opt[5];
    while(Q--){
        scanf("%s",opt);
        int x=read(),y=read();
        if(opt[1]=='C'){
            W=-a[x].w,pos=in[x],modify(a[x].c);
            W=a[x].w,modify(a[x].c=y);
        }else if(opt[1]=='W')
            W=y-a[x].w,pos=in[x],modify(a[x].c),a[x].w=y;
        else{
            Node p=Query(x,y);
            printf("%d\n",opt[1]=='S'? p.s:p.mx);
        }
    }
}
posted @ 2021-04-06 19:07  Kreap  阅读(57)  评论(0编辑  收藏  举报