• 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
    ",qs(x,y));
            else printf("%d
    ",qm(x,y));
        }
        return 0;
    }

    By Charlie Pan

    Mar 14,2014

    

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    AVFrame中data与linesize关系
    使用gprof2dot和graphivz生成程序运行调用图
    C/C++ 数组复制
    32位和64位系统区别及int字节数
    ffmpeg中AVPacket与AVFrame中数据的传递与释放
    C/C++输入一行每隔一个空格一个数据
    为什么软件项目需要架构设计?
    绘制函数调用图(call graph):doxygen + graphviz
    复制解码的 ffmpeg AVFrame
    360文档卫士——防勒索,通过即时的预警监测机制,360文档卫士能够“自动备份”您的文档。只要“监测到文档产生任何编辑或动作”,360文档卫士便会!!自动存取!!最新版本
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4646605.html
Copyright © 2020-2023  润新知