zoukankan      html  css  js  c++  java
  • CH6303 天天爱跑步

    描述

    小C同学认为跑步非常有趣,于是决定制作一款叫作《天天爱跑步》的游戏。《天天爱跑步》是一个养成类游戏,需要玩家每天按时上线,完成打卡任务。
    这个游戏的地图可以看作一棵包含 n (n≤3*10^5) 个节点和 n-1 条边的树,任意两个节点存在一条路径互相可达。树上节点的编号是 1~n 之间的连续正整数。
    现在有 m (m≤3*10^5) 个玩家,第 i 个玩家的起点为 S_i,终点为 T_i。每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发,以每秒跑一条边的速度,不间断地沿着最短路径向着自己的终点跑去,跑到终点后该玩家就算完成了打卡任务。因为地图是一棵树,所以每个人的路径是唯一的。
    小C想知道游戏的活跃度,所以在每个节点上都放置了一个观察员。在节点 j 的观察员会选择在第 W_j 秒观察玩家,一个玩家能被这个观察员观察到当且仅当该玩家在第 W_j 秒也正好到达了节点 j。小C想知道每个观察员会观察到多少人?
    注意:我们认为一个玩家到达自己的终点后,该玩家就会结束游戏,他不能等待一段时间后再被观察员观察到。即对于把节点 j 作为终点的玩家:若他在第 W_j 秒前到达终点,则在节点 j 的观察员不能观察到该玩家;若他正好在第 W_j 秒到达终点,则在节点 j 的观察员可以观察到这个玩家。

    输入格式

    第一行有两个整数N和M 。其中N代表树的结点数量, 同时也是观察员的数量, M代表玩家的数量。
    接下来n-1 行每行两个整数U和V ,表示结点U 到结点V 有一条边。
    接下来一行N 个整数,其中第个整数为Wj , 表示结点出现观察员的时间。
    接下来 M行,每行两个整数Si和Ti,表示一个玩家的起点和终点。
    对于所有的数据,保证 1<=Si,Ti<=N,0<=Wj<=N。

    输出格式

    一行 N 个整数,第 i 个整数表示结点 i 的观察员可以观察到多少人。

    样例输入

    样例输入1
    6 3
    2 3
    1 2 
    1 4 
    4 5 
    4 6 
    0 2 5 1 2 3 
    1 5 
    1 3 
    2 6
    样例输入2
    5 3 
    1 2 
    2 3 
    2 4 
    1 5 
    0 1 0 3 0 
    3 1 
    1 4
    5 5 

    样例输出

    样例输入1
    2 0 0 1 1 1
    样例输入2
    1 2 1 0 1 

    数据范围与约定

    样例解释

    在第一个样例中,对于1号点,W1=0,故只有起点为1号点的玩家才会被观察到,所以玩家1和玩家2被观察到,共2人被观察到。
    对于2号点,没有玩家在第2秒时在此结点,共0人被观察到。
    对于3号点,没有玩家在第5秒时在此结点,共0人被观察到。
    对于4号点,玩家1被观察到,共1人被观察到。
    对于5号点,玩家1被观察到,共1人被观察到。
    对于6号点,玩家3被观察到,共1人被观察到。

    来源

    CCF NOIP2016 D1T2

            </article>
    

    题解

    分为两段,可以分开做:

    1. (S_i)处产生(d[S_i]),在(fa[lca(S_i,T_i)])处减去它,在任意节点(x)处统计(W[x]+d[x])的个数。
    2. (T_i)处产生(d[S_i]-2*d[lca(S_i,T_i)]),在(lca(S_i,T_i))处减去它,在任意节点(x)处统计(W[x]-d[x])的个数。

    而这个用不着线段树合并,直接用在每个节点用vector存一下变动,开全局数组统计,用末值减去初值就是答案了。

    时间复杂度(O(mlog n+n))

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
        for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef long long ll;
    using namespace std;
    
    co int N=3e5+1;
    int n,m,t;
    vector<int> e[N];
    int fa[N][20],dep[N];
    void bfs(){
    	t=log(n)/log(2);
    	queue<int> q;
    	dep[1]=1,q.push(1);
    	for(int x;q.size();){
    		x=q.front(),q.pop();
    		for(int i=0,y;i<e[x].size();++i){
    			if(dep[y=e[x][i]]) continue;
    			dep[y]=dep[x]+1,fa[y][0]=x;
    			for(int j=1;j<=t;++j) fa[y][j]=fa[fa[y][j-1]][j-1];
    			q.push(y);
    		}
    	}
    }
    int lca(int x,int y){
    	if(dep[x]>dep[y]) swap(x,y);
    	for(int i=t;i>=0;--i)
    		if(dep[fa[y][i]]>=dep[x]) y=fa[y][i];
    	if(x==y) return x;
    	for(int i=t;i>=0;--i)
    		if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    
    int w[N],c1[N*2],c2[N*2],ans[N];
    vector<int> a1[N],b1[N],a2[N],b2[N];
    void dfs(int x){
    	int val1=c1[dep[x]+w[x]],val2=c2[w[x]-dep[x]+n];
    	for(int i=0,y;i<e[x].size();++i)
    		if((y=e[x][i])!=fa[x][0]) dfs(y);
    	for(int i=0;i<a1[x].size();++i) ++c1[a1[x][i]];
    	for(int i=0;i<b1[x].size();++i) --c1[b1[x][i]];
    	for(int i=0;i<a2[x].size();++i) ++c2[a2[x][i]+n];
    	for(int i=0;i<b2[x].size();++i) --c2[b2[x][i]+n];
    	ans[x]=c1[dep[x]+w[x]]-val1+c2[w[x]-dep[x]+n]-val2;
    }
    int main(){
    	read(n),read(m);
    	for(int i=1,x,y;i<n;++i){
    		read(x),read(y);
    		e[x].push_back(y),e[y].push_back(x);
    	}
    	bfs();
    	for(int i=1;i<=n;++i) read(w[i]);
    	for(int i=1,x,y,z;i<=m;++i){
    		read(x),read(y),z=lca(x,y);
    		a1[x].push_back(dep[x]),b1[fa[z][0]].push_back(dep[x]);
    		a2[y].push_back(dep[x]-2*dep[z]),b2[z].push_back(dep[x]-2*dep[z]);
    	}
    	dfs(1);
    	for(int i=1;i<=n;++i) printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/autoint/p/10934990.html
Copyright © 2011-2022 走看看