• Noip2016Day1T2 天天爱跑步


    题目链接

    problem

    solution

    这是一道一个顶六个的好题!!!

    说一下各档部分分怎么写吧。

    先看一下(S_i=1)(T_i=1)的部分分怎么写。

    如果(S_i=1)

    当且仅当第(i)个点的深度(dep_i=w_i)时,该点可以观察到人。且观察到的人数为终点位于其子树内的人数。

    如果(T_i=1)

    这时第(i)个点能观察到的人数就是子树内起点深度=(dep_i+w[i])的人数。用个桶记录下来这个值。

    如果得到该子树内(dep[s_i]=dep_i+w[i])的数量呢?

    其实很简单。当第一次(bfs)到点(i)时,记录下桶中(dep_i+w[i])的值,(dfs)整颗子树之后再得到一个值。将两个值作差即可。

    下面说满分做法

    将路径分为从(s)(lca)和从(lca)(t)两部分讨论。

    先看从(s)(lca)这部分。

    那么对于一个点(i)就是要找(dep[lca]<=dep[i])(dep_s=dep_i+w_i)的数量。

    不考虑红色部分限制的话,就和(S_i=1)的部分分同样做法。

    然后看(lca)(t)这部分

    对于一个点(i)就是要找(dep[lca]<=dep[i])(len - (dep[t]-dep[i])=w[i])(w[i] - dep[i] = len - dep[t])的数量((len)表示该路径长度)。
    这个不考虑红色部分限制的话,也可以用一个桶维护出来。

    然后考虑解决红色部分限制

    其实只要在dfs完一个点的子树后,将以该点为(lca)的路径贡献全部从桶中删除即可。

    code

    #include<cstdio>
    #include<iostream>
    #include<ctime>
    #include<algorithm>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0';
    		c = getchar();
    	}
    	return x * f;
    }
    int n,m;
    namespace BF1 {
    	const int N = 1010;
    	int a[N],b[N];
    	void main() {
    		
    		for(int i = 1;i < n;++i) {read();read();}
    
    		for(int i = 1;i <= n;++i) {
    			int k = read();
    			if(!k) b[i] = 1;
    		}
    
    		int ans = 0;
    		for(int i = 1;i <= m;++i) {
    			int x = read(),y = read();
    			a[x]++;
    		}
    		for(int i = 1;i <= n;++i)
    			printf("%d ",a[i] * b[i]);
    
    	}
    }
    namespace BF2 {
    	int a[1010];
    	void main() {
    		for(int i = 1;i < n;++i) {read();read();}
    		for(int i = 1;i <= n;++i) read();
    		for(int i = 1;i <= m;++i) {
    			int x = read(),y = read();
    			a[x]++;
    		}
    		for(int i = 1;i <= n;++i)
    			printf("%d ",a[i]);
    	}
    }
    namespace BF3 {
    	const int N = 1010;
    	struct node {
    		int v,nxt;
    	}e[N << 1];
    	int w[N],ans[N];
    	int head[N],ejs;
    	void add(int u,int v) {
    		e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
    	}
    	int dfs(int u,int fa,int V,int now) {
    		if(u == V) {
    			ans[u] += w[u] == now;
    			return 1;
    		}
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(v == fa) continue;
    			if(dfs(v,u,V,now + 1)) {
    				ans[u] += (w[u] == now);
    				return 1;
    			}
    		}
    		return 0;
    	}
    	void main() {
    		for(int i = 1;i < n;++i) {
    			int u = read(),v = read();
    			add(v,u);add(u,v);
    		}
    		
    		for(int i = 1;i <= n;++i) w[i] = read();
    		
    		for(int i = 1;i <= m;++i) {
    			int u = read(),v = read();
    			dfs(u,0,v,0);
    		}
    		for(int i = 1;i <= n;++i) printf("%d ",ans[i]);
    	}
    }
    namespace BF4 {
    	const int N = 100010;
    	vector<int>v[N];
    	int w[N],ans[N];
    	int erfen(int pos,int x) {
    		int l = 0,r = v[pos].size() - 1,ret = r + 1;
    		
    		while(l <= r) {
    			int mid = (l + r) >> 1;
    			if(v[pos][mid] >= x) ret = mid,r = mid - 1;
    			else l = mid + 1;
    		}
    		
    		return ret + 1;
    	}
    	void main() {
    		for(int i = 1;i < n;++i) read(),read();
    		for(int i = 1;i <= n;++i) w[i] = read();
    		for(int i = 1;i <= m;++i) {
    			int u = read(),V = read();
    			v[u].push_back(V);
    		}
    		for(int i = 1;i <= n;++i) sort(v[i].begin(),v[i].end());
    		
    		for(int i = 1;i <= n;++i) {
    			int k = i - w[i];
    			if(w[i] == 0) {
    				ans[i] += v[k].size();continue;
    			}
    			if(k > 0) {
    //				int p = erfen(k,i);
    //				ans[i] += v[k].size() - p + 1;
    				for(vector<int>::iterator it = v[k].begin();it != v[k].end();++it) {
    					if(*it >= i) ans[i]++;
    				}
    			}
    			k = i + w[i];
    			if(k <= n) {
    //				int p = erfen(k,i);
    //				ans[i] += p - 1;
    				for(vector<int>::iterator it = v[k].begin();it != v[k].end();++it) 
    				if(*it <= i) ans[i]++;
    			}
    		}
    		for(int i = 1;i <= n;++i) printf("%d ",ans[i]);
    	}
    }
    namespace BF5 {
    	const int N = 100010;
    	struct node {
    		int v,nxt;
    	}e[N << 1];
    	int head[N],ejs;
    	void add(int u,int v) {
    		e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
    	}
    	int siz[N],dep[N];
    	void dfs(int u,int fa) {
    		dep[u] = dep[fa] + 1;
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(v == fa) continue;
    			dfs(v,u);
    			siz[u] += siz[v];
    		}
    	}
    	int w[N];
    	void main() {
    		for(int i = 1;i < n;++i) {
    			int u = read(),v = read();
    			add(u,v);add(v,u);
    		}
    		for(int i = 1;i <= n;++i) w[i] = read();
    		for(int i = 1;i <= m;++i) {
    			int x = read(),y = read();
    			siz[y]++;
    		}
    		dep[0] = -1;
    		dfs(1,0);
    		for(int i = 1;i <= n;++i) {
    			if(dep[i] == w[i]) printf("%d ",siz[i]);
    			else printf("0 ");
    		}
    	}
    }
    namespace BF6 {
    	const int N = 100010;
    	struct node {
    		int v,nxt;
    	}e[N << 1];
    	int head[N],ejs;
    	void add(int u,int v) {
    		e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
    	}
    	int w[N],dep[N],ans[N];
    	int tong[N << 1],siz[N << 1];
    	void solve(int u,int fa) {
    		dep[u] = dep[fa] + 1;
    		int k = tong[dep[u] + w[u]];
    		tong[dep[u]] += siz[u];
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(v == fa) continue;
    			solve(v,u);
    		}
    		ans[u] = tong[dep[u] + w[u]] - k;
    	}
    	void main() {
    		for(int i = 1;i < n;++i) {
    			int u = read(),v = read();
    			add(v,u);add(u,v);
    		}
    		
    		for(int i = 1;i <= n;++i) w[i] = read();
    		for(int i = 1;i <= m;++i) {
    			int x = read(),y = read();
    			siz[x]++;
    		}
    		
    		
    		solve(1,0);
    		for(int i = 1;i <= n;++i) printf("%d ",ans[i]);
    	}
    }
    namespace BF7 {
    	const int N = 300000,logN = 20;
    	struct node {
    		int v,nxt;
    	}e[N << 1];
    	int head[N],ejs;
    	void add(int u,int v) {
    		e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
    	}
    	int dep[N],w[N],lca[N][20];
    	void get_lca(int u,int fa) {
    		dep[u] = dep[fa] + 1;
    		for(int i = 1;i < logN;++i)	lca[u][i] = lca[lca[u][i - 1]][i - 1];
    		
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v =  e[i].v;
    			if(v == fa) continue;
    			lca[v][0] = u;
    			get_lca(v,u);
    		}
    	}
    	int LCA(int x,int y) {
    		if(dep[x] < dep[y]) swap(x,y);
    		
    		for(int i = logN - 1;i >= 0;--i)
    			if(dep[lca[x][i]] >= dep[y]) x = lca[x][i];
    
    		for(int i = logN - 1;i >= 0;--i)
    			if(lca[x][i] != lca[y][i]) x = lca[x][i],y = lca[y][i];
    		
    		if(x == y) return x;
    		return lca[x][0];
    	}
    	vector<int>vs[N],vt[N],st[N];
    	int ans[N],siz[N];
    	int stong[N << 1],ttong[N << 1];
    	void dfs(int u,int fa) {
    		int ks = stong[dep[u] + w[u]],kt = ttong[w[u] - dep[u] + N];
    		stong[dep[u]] += siz[u];
    		for(vector<int>::iterator it = st[u].begin();it != st[u].end();++it) ttong[*it]++;
    	
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(v != fa) dfs(v,u);
    		}
    		
    		for(vector<int>::iterator it = vt[u].begin();it != vt[u].end();++it) ttong[*it]--;
    	
    		ans[u] = stong[dep[u] + w[u]] - ks + ttong[w[u] - dep[u] + N] - kt;
    		
    		for(vector<int>::iterator it = vs[u].begin();it != vs[u].end();++it) stong[*it]--;
    		
    	}
    	void main() {
    		for(int i = 1;i < n;++i) {
    			int u = read(),v = read();
    			add(u,v);add(v,u);
    		}
    		for(int i = 1;i <= n;++i) w[i] = read();
    		get_lca(1,0);
    		
    		for(int i = 1;i <= m;++i) {
    			int s = read(),t = read();
    			int k = LCA(s,t),len = dep[s] + dep[t] - dep[k] * 2;
    			vs[k].push_back(dep[s]);
    			vt[k].push_back(len - dep[t] + N);
    			st[t].push_back(len - dep[t] + N);
    			siz[s]++;
    		}
    		
    		dfs(1,0);
    		for(int i = 1;i <= n;++i) printf("%d ",ans[i]);
    	}
    }
    int main() {
    	n = read(),m = read();
    	if(n == 991) {BF1::main();return 0;}
    	if(n == 992) {BF2::main();return 0;}
    	if(n == 993) {BF3::main();return 0;}
    	if(n == 99994) {BF4::main();return 0;}
    	if(n == 99995) {BF5::main();return 0;}
    	if(n == 99996) {BF6::main();return 0;}
    	BF7::main();
    	return 0;
    }
    
    /*
    5 3
    1 2
    2 3
    3 4
    4 5
    1 1 2 2 3
    2 4
    1 3
    1 5
    
    
    
    7 4
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    1 1 1 2 3 2 4
    1 2
    1 5
    1 6
    1 7
    
    7 4
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    2 1 1 1 1 0 1 
    4 1
    5 1
    6 1
    7 1
    */
    
    
  • 相关阅读:
    Jmeter正则提取list中相同key的value和出现的次数
    Jmeter正则提取器常用的几种方式
    浅谈python 手机crash和app crash循环执行问题
    python中try except处理程序异常的三种常用方法
    支付功能测试总结
    web搜索功能测试
    日常linux命令
    sql进阶练习题
    常见问题集锦
    HTML+CSS基础
  • 原文地址:https://www.cnblogs.com/wxyww/p/Noip2016Day1T2.html
Copyright © 2020-2023  润新知