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

    洛咕

    给定一棵(n(n<=3*10^5))个点的树,指定一条路径为(a[1]->a[2]->...->a[n]),求每个点被经过了多少次.

    分析:树上差分中的点差分.还是先跑一遍DFS预处理出LCA,然后对于每一对(a[i],a[i+1])按照点差分的常规操作处理即可.然后再跑一遍DFS向上回溯时累加就好.最后因为对于中间的(i(2<=i<=n-1)),我们都加了两次,所以输出答案前都要(-1).然后题目说了(a[n])不需要算进去,所以输出答案前(a[n])也要(-1).

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=300005;
    const int M=600005;
    int a[N],dep[N],cnt[N],f[N][25];
    int tot,head[N],nxt[M],to[M];
    inline void add(int a,int b){
    	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
    }
    inline void dfs(int u,int fa){
    	dep[u]=dep[fa]+1;
    	for(int j=1;j<=20;++j)
    		f[u][j]=f[f[u][j-1]][j-1];
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(v==fa)continue;
    		f[v][0]=u;dfs(v,u);
    	}
    }
    inline int LCA(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        for(int j=20;j>=0;--j){
            if(dep[f[x][j]]>=dep[y])x=f[x][j];
            if(x==y)return x;
        }
        for(int j=20;j>=0;--j)
            if(f[x][j]!=f[y][j]){
                x=f[x][j];
                y=f[y][j];
            }
        return f[x][0];
    }
    inline void dp(int u,int fa){
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(v==fa)continue;
    		dp(v,u);cnt[u]+=cnt[v];
    	}
    }
    int main(){
    	int n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<n;++i){
    		int a=read(),b=read();
    		add(a,b);add(b,a);
    	}
    	dfs(1,0);
    	for(int i=1;i<n;++i){
    		int lca=LCA(a[i],a[i+1]);
    		++cnt[a[i]];++cnt[a[i+1]];
    		--cnt[lca];--cnt[f[lca][0]];
    	}
    	dp(1,0);for(int i=2;i<=n;++i)--cnt[a[i]];
    	for(int i=1;i<=n;++i)printf("%d
    ",cnt[i]);
        return 0;
    }
    
    
  • 相关阅读:
    c标签页面进行解析json
    Android 简述touch事件中的MotionEvent
    R中读取文件,找不到路径问题 No such file or directory
    文章标题
    Codeforces Beta Round #2 C. Commentator problem
    openfire 开发遇到的些问题
    BZOJ 刷题记录 PART 5
    公司又裁人了……
    最简单的基于FFmpeg的移动端样例:Android 视频转码器
    单片机: 简易计算器的实现(键盘)
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11439378.html
Copyright © 2011-2022 走看看