题目链接

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
*/

Noip2016Day1T2 天天爱跑步的更多相关文章

  1. [NOIP2016-day1-T2]天天爱跑步running_题解

    题目来源:http://www.lydsy.com/JudgeOnline/problem.php?id=4719 镇楼图: noip滚粗后..订正的第一题. 题目大意: 有若干条路径在一棵树上,问每 ...

  2. NOIP2016Day1T2天天爱跑步(LCA+桶)

    据说是今年NOIP最难一题了...我还记得当时满怀期待心情点开Day1的题发现T2就不会了于是怀疑人生良久... 啊好像很多大爷都是用线段树合并写的,我怎么什么数据结构都不会啊呜呜呜... 题目大意就 ...

  3. UOJ261 【NOIP2016】天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  4. BZOJ4719 [Noip2016]天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  5. noip2016天天爱跑步

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点 ...

  6. bzoj 4719: [Noip2016]天天爱跑步

    Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一 ...

  7. [NOIP]2016天天爱跑步

    [NOIP]2016天天爱跑步 标签: LCA 树上差分 NOIP Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...

  8. NOIP2016 天天爱跑步 80分暴力

    https://www.luogu.org/problem/show?pid=1600 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养 ...

  9. [NOIp 2016]天天爱跑步

    Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图 ...

随机推荐

  1. 好的js书写习惯

    1:单一判断 bad if (result) { console.log("秋叶"); } if (!result) { console.log("秋叶"); ...

  2. 初步了解Node.js,学做简单的留言本案例

    在还没有正式的学Node.js的时候, 你们认为Node.js 对于前端来说是什么呢? 会认为Node.js 是框架? 认为这是类似Jquery的一个快速.简洁的JavaScript框架? 反正我自己 ...

  3. 「SAP技术」如何看Z移动类型是复制哪个标准移动类型而创建的?

    [SAP技术]SAP MM 如何看一个自定义移动类型是复制哪个标准移动类型而创建的? 比如项目上有一个自定义移动类型Z59,是复制551移动类型而定义的. OMJJ配置界面里,是有一个Ref字段.如下 ...

  4. Jerome: Vulnhub Walkthrough

    nmap 扫描探测: ╰─ nmap -p1-65535 -sV -A -O -sT 10.10.202.135Starting Nmap 7.70 ( https://nmap.org ) at 2 ...

  5. Android 弹出Dialog时隐藏状态栏和底部导航栏

    上代码 dialog.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); di ...

  6. 轻松定位CPU飙高问题

    以下四步轻松定位CPU飙高问题: ①top pid 查看cpu耗CPU进程 ②top -Hp pid 查看该进程所有线程的运行情况,找到占用 CPU 过高的线程 pid ③ printf %x pid ...

  7. linux离线安装mysql5.7

    下载安装包 下载地址:https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.27-1.el7.x86_64.rpm-bundle.tar 上传到 / ...

  8. ABC135记录

    date: 2019-07-28 A - Harmony 题目大意: 给你两个不同的整数A和B,要求你找到一个整数K,同时满足|A-K|=|B-K|.找不到时,输出"IMPOSSIBLE&q ...

  9. java之this关键字和super关键字的区别

    编号 区别点 this super 1 访问属性 访问本类中的属性,如果本类没有此 属性则从父类中继续查找 访问父类中的属性 2 调用方法 访问本类中的方法 直接访问父类中的方法 3 调用构造器 调用 ...

  10. VS出现未加载wntdll.pdb的解决办法

    无缘无故出现了未加载wntdll.pdb的的错误,不知道原因是什么,但找到了解决方法.在调试中选择选项,然后选择调试->符号,勾选Microsoft符号服务器,确定.重新生成项目时会有各种加载, ...