NOIP2016 天天爱跑步 线段树合并_桶_思维题
Description
Input
Output
输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。
Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 400000
#define M 1000000
#define plus pl
#define minus mi
using namespace std;
vector<int>plus[M],minus[M];
int n,m;
int hd[maxn<<1],to[maxn<<1],nx[maxn<<1],edges;
int dep[maxn],F[22][maxn],tim[maxn],st[maxn],ed[maxn];
int answer[maxn];
void add(int u,int v){
nx[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs1(int u,int fa){
dep[u]=dep[fa]+1;
F[0][u]=fa;
for(int i=1;i<22;++i) F[i][u]=F[i-1][F[i-1][u]];
for(int v=hd[u];v;v=nx[v])
if(to[v]!=fa) dfs1(to[v],u);
}
int lca(int a,int b){
if(dep[a]>dep[b]) swap(a,b);
if(dep[a]!=dep[b]) for(int i=21;i>=0;--i) if(dep[F[i][b]]>=dep[a]) b=F[i][b];
if(a==b) return a;
for(int i=21;i>=0;--i) if(F[i][a]!=F[i][b]) a=F[i][a],b=F[i][b];
return F[0][a];
}
int tot,root[maxn];
struct Node{ int l,r,w; }node[maxn*11];
#define mid ((l+r)>>1)
void ins(int &o,int k,int delta,int l,int r){
if(!o) o=++tot;
node[o].w+=delta;
if(l==r) return;
else{
if(k<=mid) ins(node[o].l,k,delta,l,mid);
else ins(node[o].r,k,delta,mid+1,r);
}
}
int merge(int x,int y){
if(!x||!y) return x+y;
node[x].w+=node[y].w;
node[x].l=merge(node[x].l,node[y].l);
node[x].r=merge(node[x].r,node[y].r);
return x;
}
int query(int x,int l,int r,int k){
if(!x) return 0;
if(l==r) return node[x].w;
if(k<=mid) return query(node[x].l,l,mid,k);
else return query(node[x].r,mid+1,r,k);
}
void dfs2(int u){
for(int sz=plus[u].size(),i=0;i<sz;++i) ins(root[u],plus[u][i],1,1,M);
for(int sz=minus[u].size(),i=0;i<sz;++i) ins(root[u],minus[u][i],-1,1,M);
plus[u].clear(),minus[u].clear();
for(int v=hd[u];v;v=nx[v])
if(to[v]!=F[0][u]) dfs2(to[v]),root[u]=merge(root[u],root[to[v]]);
answer[u]+=query(root[u],1,M,tim[u]+dep[u]);
}
void dfs3(int u){
for(int sz=plus[u].size(),i=0;i<sz;++i) ins(root[u],plus[u][i],1,1,M);
for(int sz=minus[u].size(),i=0;i<sz;++i) ins(root[u],minus[u][i],-1,1,M);
for(int v=hd[u];v;v=nx[v])
if(to[v]!=F[0][u]) dfs3(to[v]),root[u]=merge(root[u],root[to[v]]);
answer[u]+=query(root[u],1,M,dep[u]-tim[u]+maxn);
}
void up(){
for(int i=1,c;i<=m;++i){
c=lca(st[i],ed[i]);
if(dep[c]<dep[st[i]]) {
plus[st[i]].push_back(dep[st[i]]);
minus[F[0][c]].push_back(dep[st[i]]);
}
}
dfs2(1);
memset(node,0,sizeof(node));
memset(root,0,sizeof(root));
tot=0;
}
void down(){
for(int i=1,c,pre;i<=m;++i) {
c=lca(st[i],ed[i]);
if(dep[c]<dep[ed[i]]) {
pre=dep[st[i]]-dep[c];
if(st[i]==c){
plus[ed[i]].push_back(dep[c]-pre+maxn);
minus[F[0][c]].push_back(dep[c]-pre+maxn);
}else {
plus[ed[i]].push_back(dep[c]-pre+maxn);
minus[c].push_back(dep[c]-pre+maxn);
}
}
}
dfs3(1);
}
int main(){
//setIO("input");
scanf("%d%d",&n,&m);
for(int i=1,a,b;i<n;++i) scanf("%d%d",&a,&b),add(a,b),add(b,a);
dfs1(1,0);
for(int i=1;i<=n;++i) scanf("%d",&tim[i]);
for(int i=1;i<=m;++i) {
scanf("%d%d",&st[i],&ed[i]);
if(st[i]==ed[i] && tim[st[i]]==0) ++answer[st[i]];
}
up(),down();
for(int i=1;i<=n;++i) printf("%d ",answer[i]);
return 0;
}
NOIP2016 天天爱跑步 线段树合并_桶_思维题的更多相关文章
- [NOIp2016]天天爱跑步 线段树合并
[NOIp2016]天天爱跑步 LG传送门 作为一道被毒瘤出题人们玩坏了的NOIp经典题,我们先不看毒瘤的"动态爱跑步"和"天天爱仙人掌",回归一下本来的味道. ...
- 2018.08.09 bzoj4719: [Noip2016]天天爱跑步(树链剖分)
传送门 话说开始上文化课之后写题时间好少啊. 这道题将一个人的跑步路线拆成s->lca,lca->t,然后对于第一段上坡路径要经过的点,当前这个人能对它产生贡献当且仅当dep[s]-dep ...
- [Vani有约会]雨天的尾巴 线段树合并
[Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...
- CF700E Cool Slogans——SAM+线段树合并
RemoteJudge 又是一道用线段树合并来维护\(endpos\)的题,还有一道见我的博客CF666E 思路 先把\(SAM\)建出来 如果两个相邻的串\(s_i\)和\(s_{i+1}\)要满足 ...
- LOJ #2359. 「NOIP2016」天天爱跑步(倍增+线段树合并)
题意 LOJ #2359. 「NOIP2016」天天爱跑步 题解 考虑把一个玩家的路径 \((x, y)\) 拆成两条,一条是 \(x\) 到 \(lca\) ( \(x, y\) 最近公共祖先) 的 ...
- [NOIP2016 DAY1 T2]天天爱跑步-[差分+线段树合并][解题报告]
[NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description ...
- [NOIP2016]天天爱跑步(树上差分+线段树合并)
将每个人跑步的路径拆分成x->lca,lca->y两条路径分别考虑: 对于在点i的观察点,这个人(s->t)能被观察到的充要条件为: 1.直向上的路径:w[i]=dep[s]-dep ...
- BZOJ4719 NOIP2016天天爱跑步(线段树合并)
线段树合并的话这个noip最难题就是个裸题了. 注意merge最后return x,以及如果需要区间查询的话这里还需要up,无数次死于这里. #include<iostream> #inc ...
- 【bzoj4719】[Noip2016]天天爱跑步 权值线段树合并
题目描述 给出一棵n个点的树,以及m次操作,每次操作从起点向终点以每秒一条边的速度移动(初始时刻为0),最后对于每个点询问有多少次操作在经过该点的时刻为某值. 输入 第一行有两个整数N和M .其中N代 ...
随机推荐
- svn_精简版【极速安装】
1.进入官网下载:http://tortoisesvn.net/ 2.进行安装. 3.官方下载汉化包 [32 位,64位] 4.安装完汉化包后,右键->Settings 5.选择语言包,确定就o ...
- flask-sqlalchemy 配置 mysql (转载的文章)
一.当然是把必备的包给安装上才行: Flask-SQLAlchemy pip install flask-sqlalchemy MySQL windows下64位压缩包的安装方式可以参考: http: ...
- linux下Qt程序编译运行
Qt程序编译运行很简单,利用Qt提供的qmake工具可以很好的进行编译,在命令行输入一下编译过程:qmake -project //声称项目文件(*.pro)qmake ...
- 运行npm run watch时报:events.js:182 throw er; // Unhandled 'error' event
I had this issue i did the following steps and i have no issues anymore: Delete node_modules directo ...
- Merging into a Table: Example
Merging into a Table: Example The following example uses the bonuses table in the sample schema oe w ...
- 洛谷 P2587 BZOJ 1034 [ZJOI2008]泡泡堂
题目描述 //不知道为什么BZOJ和洛谷都没有这幅图了,大牛们几年前的博客上都有这幅图的,把它贴上来吧 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省 ...
- [bzoj4487][Jsoi2015]染色_容斥原理
染色 bzoj-4487 Jsoi-2015 题目大意:给你一个n*m的方格图,在格子上染色.有c中颜色可以选择,也可以选择不染.求满足条件的方案数,使得:每一行每一列都至少有一个格子被染色,且所有的 ...
- 基于java注解实现自己的orm框架
ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关系. 现在常见的 ...
- mysql配置文件夹错误:在安装mysql 5.6.19 时运行cmake命令是出现CMake Error: The source directory does not appear to contai
在安装mysql 5.5.xx 时运行cmake命令是出现CMake Error: The source directory does not appear to contain CMakeLists ...
- Java与设计模式-策略模式
在实际开发中,可能会遇到这样一个情况,某一功能的实现分为多种算法,这些算法能够认定为策略,在实际操作时选择不同算法或策略进行操作得出终于结果.在实际生活中.这些样例也是举不胜举.比如.商场举行活动,满 ...