BZOJ4719 NOIP2016天天爱跑步(线段树合并)
线段树合并的话这个noip最难题就是个裸题了。
注意merge最后return x,以及如果需要区间查询的话这里还需要up,无数次死于这里。
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstdlib>
- #include<cstring>
- #include<algorithm>
- #include<vector>
- using namespace std;
- int read()
- {
- int x=,f=;char c=getchar();
- while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
- while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
- return x*f;
- }
- #define N 300010
- int n,m,p[N],a[N],fa[N][],deep[N],ans[N],root[][N],cnt[]={},t=;
- vector<int> op1[N],op2[N];
- struct data{int to,nxt;
- }edge[N<<];
- struct data2{int l,r,x;
- }tree[][N<<];
- void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
- void dfs(int k)
- {
- for (int i=p[k];i;i=edge[i].nxt)
- if (edge[i].to!=fa[k][])
- {
- fa[edge[i].to][]=k;
- deep[edge[i].to]=deep[k]+;
- dfs(edge[i].to);
- }
- }
- int lca(int x,int y)
- {
- if (deep[x]<deep[y]) swap(x,y);
- for (int j=;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];
- if (x==y) return x;
- for (int j=;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
- return fa[x][];
- }
- int merge(int x,int y,int l,int r,int p)
- {
- if (!x||!y) return x|y;
- if (l==r) {tree[p][x].x+=tree[p][y].x;return x;}
- int mid=l+r>>;
- tree[p][x].l=merge(tree[p][x].l,tree[p][y].l,l,mid,p);
- tree[p][x].r=merge(tree[p][x].r,tree[p][y].r,mid+,r,p);
- return x;
- }
- void ins(int &k,int x,int l,int r,int v,int p)
- {
- if (!k) k=++cnt[p];
- if (l==r) {tree[p][k].x+=v;return;}
- int mid=l+r>>;
- if (x<=mid) ins(tree[p][k].l,x,l,mid,v,p);
- else ins(tree[p][k].r,x,mid+,r,v,p);
- }
- int query(int k,int l,int r,int x,int p)
- {
- if (!k) return ;
- if (l==r) return tree[p][k].x;
- int mid=l+r>>;
- if (x<=mid) return query(tree[p][k].l,l,mid,x,p);
- else return query(tree[p][k].r,mid+,r,x,p);
- }
- void getans(int k)
- {
- for (int i=p[k];i;i=edge[i].nxt)
- if (edge[i].to!=fa[k][])
- {
- getans(edge[i].to);
- root[][k]=merge(root[][k],root[][edge[i].to],,n<<,);
- root[][k]=merge(root[][k],root[][edge[i].to],,n<<,);
- }
- for (int i=;i<op1[k].size();i++)
- if (op1[k][i]>) ins(root[][k],op1[k][i],,n<<,,);
- else ins(root[][k],-op1[k][i],,n<<,-,);
- for (int i=;i<op2[k].size();i++)
- if (op2[k][i]>) ins(root[][k],op2[k][i],,n<<,,);
- else ins(root[][k],-op2[k][i],,n<<,-,);
- ans[k]+=query(root[][k],,n<<,deep[k]+a[k],)+query(root[][k],,n<<,deep[k]-a[k]+n,);
- }
- int main()
- {
- #ifndef ONLINE_JUDGE
- freopen("bzoj4719.in","r",stdin);
- freopen("bzoj4719.out","w",stdout);
- #endif
- n=read(),m=read();
- for (int i=;i<n;i++)
- {
- int x=read(),y=read();
- addedge(x,y),addedge(y,x);
- }
- fa[][]=;dfs();
- for (int j=;j<;j++)
- for (int i=;i<=n;i++)
- fa[i][j]=fa[fa[i][j-]][j-];
- for (int i=;i<=n;i++) a[i]=read();
- for (int i=;i<=m;i++)
- {
- int x=read(),y=read(),l=lca(x,y);
- if (l!=x) op1[x].push_back(deep[x]),op1[l==?:fa[l][]].push_back(-deep[x]);
- if (l!=y) op2[y].push_back(deep[l]*-deep[x]+n),op2[l==x?(l==?:fa[l][]):l].push_back(deep[x]-deep[l]*-n);
- if (l==x&&l==y&&a[l]==) ans[l]++;
- }
- getans();
- for (int i=;i<=n;i++) printf("%d ",ans[i]);
- return ;
- }
BZOJ4719 NOIP2016天天爱跑步(线段树合并)的更多相关文章
- [NOIp2016]天天爱跑步 线段树合并
[NOIp2016]天天爱跑步 LG传送门 作为一道被毒瘤出题人们玩坏了的NOIp经典题,我们先不看毒瘤的"动态爱跑步"和"天天爱仙人掌",回归一下本来的味道. ...
- NOIP2016 天天爱跑步 线段树合并_桶_思维题
竟然独自想出来了,好开心 Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r&q ...
- 2018.08.09 bzoj4719: [Noip2016]天天爱跑步(树链剖分)
传送门 话说开始上文化课之后写题时间好少啊. 这道题将一个人的跑步路线拆成s->lca,lca->t,然后对于第一段上坡路径要经过的点,当前这个人能对它产生贡献当且仅当dep[s]-dep ...
- BZOJ4719 [Noip2016]天天爱跑步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- 【bzoj4719】[Noip2016]天天爱跑步 权值线段树合并
题目描述 给出一棵n个点的树,以及m次操作,每次操作从起点向终点以每秒一条边的速度移动(初始时刻为0),最后对于每个点询问有多少次操作在经过该点的时刻为某值. 输入 第一行有两个整数N和M .其中N代 ...
- 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 ...
- 洛谷P1600 天天爱跑步(线段树合并)
小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn ...
随机推荐
- tkinter菜单图标,工具栏
所用的图片: import tkinter as tk from tkinter import messagebox, filedialog, simpledialog, colorchooser f ...
- 【LG3973】[TJOI2015]线性代数
[LG3973][TJOI2015]线性代数 题面 洛谷 题解 正常解法 一大堆矩阵乘在一起很丑对吧 化一下柿子: \[ D=(A*B-C)*A^T\\ \Leftrightarrow D=\sum_ ...
- 【BZOJ4803】逆欧拉函数
[BZOJ4803]逆欧拉函数 题面 bzoj 题解 题目是给定你\(\varphi(n)\)要求前\(k\)小的\(n\). 设\(n=\prod_{i=1}^k{p_i}^{c_i}\) 则\(\ ...
- 利用 Intel Realsense做SLAM开发(一)
最近手里拿到一台Realsense D435,就是这个: https://click.intel.com/intelr-realsensetm-depth-camera-d435.html 所以准备拿 ...
- C++自学第一课:函数
此贴并非教学,主要是自学笔记,所述内容只是些许个人学习心得的记录和备查积累,难以保证观点正确,也不一定能坚持完成. 如不幸到访,可能耽误您的时间,也难及时回复,贴主先此致歉.如偶有所得,相逢有缘,幸甚 ...
- json_encode替代函数
<?php function jsonEncode($var) { if (function_exists('json_encode')) { return json ...
- Zookeeper--java操作zookeeper
如果是使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper-3.4.5.jar 和 zkclien ...
- 高可用Kubernetes集群-4. kubectl客户端工具
六.部署kubectl客户端工具 1. 下载 [root@kubenode1 ~]# cd /usr/local/src/ [root@kubenode1 src]# wget https://sto ...
- RHCE6.0上午的考试一键完成
#!/sbin/bash # #initial envirment #variable define IPADDR=192.168.0.12 NETMASK=255.255.255.0 HOSTNAM ...
- linux 的 awk 使用
linux中awk命令对文本内容进行操作,其功能十分强大 1.如:查看一个有几百万行内容的文件中第3列数字内容(不重复) cat test.csv | awk -F ',' '{print $3}' ...