luoguP3313 [SDOI2014]旅行

除了动态点线段树和普通线段树没什么区别。。。代码量挺大?

哈哈哈1A这道题- - 还是挺不错的。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5,maxm=1e7+5;
int w[maxn],c[maxn],pos[maxn],size[maxn],top[maxn],f[maxn],dep[maxn],head[maxn],ch[maxn];
int cnt=0,sz=0,root=1,sc=0,n;
struct edge{
    int to,next;
}e[maxn*2];
struct list{
    int l,r,sum,maxx;
}tree[maxm];
void pushup(int k){
    int l=tree[k].l,r=tree[k].r;
    tree[k].sum=tree[l].sum+tree[r].sum;
    tree[k].maxx=max(tree[l].maxx,tree[r].maxx);
}
void add_edge(int s,int t){
    e[++cnt].next=head[s];e[cnt].to=t;head[s]=cnt;
    e[++cnt].next=head[t];e[cnt].to=s;head[t]=cnt;
}
void dfs1(int u){
    size[u]=1;
    for(int i=head[u];i;i=e[i].next){
        if(f[u]!=e[i].to){
            dep[e[i].to]=dep[u]+1;
            f[e[i].to]=u;
            dfs1(e[i].to);
            size[u]+=size[e[i].to];
        }
    }
}
void dfs2(int u,int ance){
    pos[u]=++sz;
    top[u]=ance;
    int k=0;
    for(int i=head[u];i;i=e[i].next){
        if(f[u]!=e[i].to&&size[k]<size[e[i].to]){
            k=e[i].to;
        }
    }
    if(k==0)return ;
    dfs2(k,ance);
    for(int i=head[u];i;i=e[i].next){
        if(f[u]!=e[i].to&&e[i].to!=k){
            dfs2(e[i].to,e[i].to);
        }
    }
}

//线段树 
void change(int &k,int l,int r,int p,int x){
    if(!k)k=++sc;
    if(l==r){
        tree[k].sum=x;
        tree[k].maxx=x;
        return ;
    }
    int mid=(l+r)>>1;
    if(mid>=p)change(tree[k].l,l,mid,p,x);
    else change(tree[k].r,mid+1,r,p,x);
    pushup(k);
}
int query1(int k,int l,int r,int tl,int tr){
    if(!k)return 0;
    if(tl<=l&&tr>=r){
        return tree[k].sum;
    }
    int mid=(l+r)>>1,ret=0;
    if(mid>=tl)ret+=query1(tree[k].l,l,mid,tl,tr);
    if(mid<tr)ret+=query1(tree[k].r,mid+1,r,tl,tr);
    return ret;
}
int query2(int k,int l,int r,int tl,int tr){
    if(!k)return 0;
    if(tl<=l&&tr>=r){
        return tree[k].maxx;
    }
    int mid=(l+r)>>1,ret=0;
    if(mid>=tl)ret=query2(tree[k].l,l,mid,tl,tr);
    if(mid<tr)ret=max(ret,query2(tree[k].r,mid+1,r,tl,tr));
    return ret;
}
int solvesum(int x,int y,int z){
    int ret=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ret+=query1(z,1,n,pos[top[x]],pos[x]);
        x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    ret+=query1(z,1,n,pos[x],pos[y]);
    return ret;
}
int solvemax(int x,int y,int z){
    int ret=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ret=max(ret,query2(z,1,n,pos[top[x]],pos[x]));
        x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    ret=max(ret,query2(z,1,n,pos[x],pos[y]));
    return ret;
}
int main(){
    int q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;++i){
        scanf("%d%d",&w[i],&c[i]);
    }
    for(int i=1;i<=n-1;++i){
        int s,t;
        scanf("%d%d",&s,&t);
        add_edge(s,t);
    }
    dfs1(root);
    dfs2(root,root);
    for(int i=1;i<=n;++i){
        change(ch[c[i]],1,n,pos[i],w[i]);
    }
    while(q--){
        char opt[3];
        int x,y;
        scanf("%s%d%d",opt,&x,&y);
        if(opt[1]=='C'){
            change(ch[c[x]],1,n,pos[x],0);
            c[x]=y;
            change(ch[c[x]],1,n,pos[x],w[x]);
        }
        else if(opt[1]=='W'){
            change(ch[c[x]],1,n,pos[x],y);
            w[x]=y;
        }
        else if(opt[1]=='S'){
            printf("%d\n",solvesum(x,y,ch[c[x]]));
        }
        else{
            printf("%d\n",solvemax(x,y,ch[c[x]]));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dream-Runner/p/9419563.html