zoukankan      html  css  js  c++  java
  • [JLOI2014]松鼠的新家

    题目:BZOJ3631、洛谷P3258。

    题目大意:有一棵n个点的树,和一个长度为n的序列a。现在要依次到达$a_1,a_2,a_3,...,a_n$节点,只能沿着树枝走。每次从一个节点到另一个节点,所经过的所有节点的点权加1(每次出发的节点除外,最后一个到达的节点不用+1,但一开始到1号节点要+1)。求最后每个点的点权。

    解题思路:树上差分。

    每次在一条路径的起点和终点+1,它们的LCA和LCA的父亲-1,最后每个节点的子树和就是最终答案。

    注意上述不用加的情况,相当于除了$a_1$,每个节点答案都要-1。

    C++ Code:

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<cctype>
    using namespace std;
    #define N 300005
    int n,ne=0,nq=0;
    bool vis[N],instack[N];
    int f[N],head[N],que[N],a[N],jz[N],zx[N],p[N];
    #define C c=getchar()
    inline int readint(){
        char C;
        bool b=false;
        while(!isdigit(c))b=c=='-',C;
        int d=0;
        while(isdigit(c)){
            d=d*10+c-'0';
            C;
        }
        return (b)?(-d):d;
    }
    struct query{
        int same,nxt,to,num;
        bool flag;
    }q[600001];
    struct edge{
        int to,nxt;
    }e[600001];
    void add_edge(int x,int y){
        e[++ne].to=y;
        e[ne].nxt=head[x];
        head[x]=ne;
        e[++ne].to=x;
        e[ne].nxt=head[y];
        head[y]=ne;
    }
    void add_que(int x,int y,int z){
        q[++nq].to=y;
        q[nq].same=nq+1;
        q[nq].num=z;
        q[nq].nxt=que[x];
        que[x]=nq;
        q[++nq].to=x;
        q[nq].same=nq-1;
        q[nq].num=z;
        q[nq].nxt=que[y];
        que[y]=nq;
    }
    int find(int x){
        if(f[x]==x)return x;
        return f[x]=find(f[x]);
    }
    void tarjan(int root){
        instack[root]=true;
        for(int i=head[root];i;i=e[i].nxt){
            int v=e[i].to;
            if(instack[v])continue;
            tarjan(v);
            f[v]=root;
            vis[v]=true;
        }
        for(int i=que[root];i;i=q[i].nxt)
        if(vis[q[i].to]&&!q[i].flag){
        	int p=find(q[i].to);
            --a[p];
            --a[zx[p]];
            q[i].flag=q[q[i].same].flag=true;
             
        }
        instack[root]=false;
    }
    void dfs(int now){
        instack[now]=true;
        for(int i=head[now];i;i=e[i].nxt)
        if(!instack[e[i].to]){
            dfs(e[i].to);
            a[now]+=a[e[i].to];
        }
    }
    void dfs2(int now){
        instack[now]=true;
        for(int i=head[now];i;i=e[i].nxt)
        if(!instack[e[i].to]){
            zx[e[i].to]=now;
            dfs2(e[i].to);
        }
    }
    int main(){
        n=readint();
        memset(vis,0,sizeof(vis));
        memset(instack,0,sizeof instack);
        for(int i=1;i<=n;i++)f[i]=i,p[i]=readint();
        for(int i=1;i<n;i++){
            int u=readint(),v=readint();
            add_edge(u,v);
        }
        memset(a,0,sizeof a);
        zx[1]=0;
        dfs2(1);
        memset(instack,0,sizeof instack);
        for(int i=1;i<n;i++){
            int x=p[i],y=p[i+1];
            ++a[x];
            ++a[y];
            add_que(x,y,i);
        }
        tarjan(1);
        memset(instack,0,sizeof instack);
        dfs(1);
    	++a[p[1]];
        for(int i=1;i<=n;i++)
        printf("%d
    ",a[i]-1);
        return 0;
    }
    
  • 相关阅读:
    java hashmap 缓存
    android 界面刷新 post send
    android 五种 布局文件
    通过枚举窗口,实现最小化到托盘中程序的窗口显示
    转 String,CString,TCHAR*,char*之间区别和联系
    标准C++ 时间日期函数
    话说程序员的职业生涯
    李开复:创业必备
    职业化的软件工程师
    让高版本ie兼容低版本
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7808930.html
Copyright © 2011-2022 走看看