首页 > 代码库 > BZOJ 3531: [Sdoi2014]旅行

BZOJ 3531: [Sdoi2014]旅行

题目地址:http :// www . lydsy . com / JudgeOnline / problem . php ? id = 3531

题目大意:见原题。

算法讨论:树链剖分。对于每种宗教开一棵线段树即可。

Code:

#include <cstdio>
#include <algorithm>

#define N 3000000
#define M 30000000
#define oo 0x7f7f7f7f

using namespace std;

int n,q,x,y,mm,tot,digit[10],w[N+10],c[N+10],next[N+10],son[N+10],ed[N+10],fa[N+10],head[N+10],heavy[N+10],
    size[N+10],deep[N+10],id[N+10],tree1[M+10],tree2[M+10],l[N+10],r[N+10],root[N+10];
bool vis[N+10];
char s[10];

void add(int x,int y){
    next[++mm]=son[x];
    son[x]=mm;
    ed[mm]=y;
}

void dfs1(int x){
    vis[x]=1;
    size[x]=1;
    for (int i=son[x];i;i=next[i]){
        int y=ed[i];
        if (!vis[y]){
            fa[y]=x;
            deep[y]=deep[x]+1;
            dfs1(y);
            size[x]+=size[y];
            if (size[y]>size[heavy[x]]) heavy[x]=y;
        }
    }
}

void dfs2(int x){
    vis[x]=1;
    id[x]=++tot;
    if (!head[x]) head[x]=x;
    if (heavy[x]){
        head[heavy[x]]=head[x];
        dfs2(heavy[x]);
    }
    for (int i=son[x];i;i=next[i]){
        int y=ed[i];
        if (!vis[y]) dfs2(y);
    }
}

void up(int rt){
    tree1[rt]=tree1[l[rt]]+tree1[r[rt]];
    tree2[rt]=max(tree2[l[rt]],tree2[r[rt]]);
}

void modify(int& rt,int lc,int rc,int x,int y){
    if (!rt) rt=++tot;
    if (lc==rc){
        tree1[rt]=y;
        tree2[rt]=y;
        return;
    }
    int mid=(lc+rc)/2;
    if (x<=mid) modify(l[rt],lc,mid,x,y);
    else modify(r[rt],mid+1,rc,x,y);
    up(rt);
}

int qsum(int rt,int lc,int rc,int L,int R){
    if (!rt) return 0;
    if (L==lc && R==rc) return tree1[rt];
    int mid=(lc+rc)/2;
    if (R<=mid) return qsum(l[rt],lc,mid,L,R);
    if (L>mid) return qsum(r[rt],mid+1,rc,L,R);
    return qsum(l[rt],lc,mid,L,mid)+qsum(r[rt],mid+1,rc,mid+1,R);
}

int qmax(int rt,int lc,int rc,int L,int R){
    if (!rt) return 0;
    if (L==lc && R==rc) return tree2[rt];
    int mid=(lc+rc)/2;
    if (R<=mid) return qmax(l[rt],lc,mid,L,R);
    if (L>mid) return qmax(r[rt],mid+1,rc,L,R);
    return max(qmax(l[rt],lc,mid,L,mid),qmax(r[rt],mid+1,rc,mid+1,R));
}

int qs(int x,int y){
    int ans=0,C=c[x];
    while (head[x]!=head[y]){
        if (deep[head[x]]<deep[head[y]]) swap(x,y);
        ans+=qsum(root[C],1,n,id[head[x]],id[x]);
        x=fa[head[x]];
    }
    if (deep[x]>deep[y]) swap(x,y);
    ans+=qsum(root[C],1,n,id[x],id[y]);
    return ans;
}

int qm(int x,int y){
    int ans=-oo,C=c[x];
    while (head[x]!=head[y]){
        if (deep[head[x]]<deep[head[y]]) swap(x,y);
        ans=max(ans,qmax(root[C],1,n,id[head[x]],id[x]));
        x=fa[head[x]];
    }
    if (deep[x]>deep[y]) swap(x,y);
    ans=max(ans,qmax(root[C],1,n,id[x],id[y]));
    return ans;
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("3531.in","r",stdin);
    freopen("3531.out","w",stdout);
    #endif
    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;++i){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1);
    for (int i=1;i<=n;++i) vis[i]=0;
    dfs2(1);
    tot=0;
    for (int i=1;i<=n;++i) modify(root[c[i]],1,n,id[i],w[i]);
    for (int i=1;i<=q;++i){
        scanf("%s%d%d",s,&x,&y);
        if (s[0]==‘C‘)
            if (s[1]==‘C‘){
                modify(root[c[x]],1,n,id[x],0);
                modify(root[y],1,n,id[x],w[x]);
                c[x]=y;
            }
            else{
                modify(root[c[x]],1,n,id[x],y);
                w[x]=y;
            }
        else if (s[1]==‘S‘) printf("%d\n",qs(x,y));
        else printf("%d\n",qm(x,y));
    }
    return 0;
}

By Charlie Pan

Mar 14,2014