bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】
这居然是我第一次写线段树合并……所以我居然在合并的时候加点结果WAWAWAMLEMLEMLE……!ro的时候居然直接指到la就行……
树上差分,每个点建一棵动态开点线段树,然后统计答案的时候合并即可
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=100005;
int n,m,h[N],cnt,de[N],fa[N],si[N],hs[N],fr[N],c[N],rt[N],tot,ans[N],d[N];
struct qwe
{
int ne,to;
}e[N<<1];
struct xds
{
int ls,rs,mx,p;
}t[7500005];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(int u,int v)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
}
void dfs1(int u,int fat)
{
fa[u]=fat;
de[u]=de[fat]+1;
si[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fat)
{
dfs1(e[i].to,u);
d[u]++;
si[u]+=si[e[i].to];
if(si[e[i].to]>si[hs[u]])
hs[u]=e[i].to;
}
}
void dfs2(int u,int top)
{
fr[u]=top;
if(!hs[u])
return;
dfs2(hs[u],top);
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fa[u]&&e[i].to!=hs[u])
dfs2(e[i].to,e[i].to);
}
int lca(int u,int v)
{//cerr<<u<<" "<<v<<endl;
for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
return de[u]<de[v]?u:v;
}
void ud(int ro)
{
if(t[ro].ls&&t[t[ro].ls].mx>=t[t[ro].rs].mx)
t[ro].p=t[t[ro].ls].p,t[ro].mx=t[t[ro].ls].mx;
else
t[ro].p=t[t[ro].rs].p,t[ro].mx=t[t[ro].rs].mx;
}
void update(int &ro,int l,int r,int p,int v)
{
if(!ro)
ro=++tot,t[ro].p=l;
if(l==r)
{//cerr<<p<<" "<<v<<" "<<t[ro].mx<<endl;
t[ro].mx+=v;
return;
}
int mid=(l+r)>>1;
if(p<=mid)
update(t[ro].ls,l,mid,p,v);
else
update(t[ro].rs,mid+1,r,p,v);
ud(ro);
}
void hb(int &ro,int la,int l,int r)
{
if(!la)
return;
if(!ro)
{
ro=la;
return;
}
if(l==r)
{
t[ro].mx+=t[la].mx;
return;
}
int mid=(l+r)>>1;
hb(t[ro].ls,t[la].ls,l,mid);
hb(t[ro].rs,t[la].rs,mid+1,r);
ud(ro);
}
// void dfs(int u)
// {
// for(int i=h[u];i;i=e[i].ne)
// if(e[i].to!=fa[u])
// {
// dfs(e[i].to);
// hb(rt[u],rt[e[i].to],1,100000);
// }
// if(t[rt[u]].mx<=0)
// ans[u]=0;
// else
// ans[u]=t[rt[u]].p;//cerr<<u<<" "<<t[rt[u]].mx<<endl;
// }
int main()
{
n=read(),m=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y),add(y,x);
}
dfs1(1,0);
dfs2(1,1);
t[0].mx=-1e9;
while(m--)
{
int x=read(),y=read(),z=read(),lc=lca(x,y);
update(rt[x],1,100000,z,1);
update(rt[y],1,100000,z,1);
update(rt[lc],1,100000,z,-1);
if(fa[lc])
update(rt[fa[lc]],1,100000,z,-1);
// cerr<<t[rt[x]].p<<" "<<t[rt[x]].mx<<" "<<t[rt[y]].p<<" "<<t[rt[y]].mx<<" "<<t[rt[lc]].p<<" "<<t[rt[lc]].mx<<" "<<t[rt[fa[lc]]].p<<" "<<t[rt[fa[lc]]].mx<<" "<<endl;
}
// dfs(1);
queue<int>q;
for(int i=1;i<=n;i++)
if(!d[i])
q.push(i);
while(!q.empty())
{
int u=q.front();//cerr<<u<<endl;
q.pop();
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fa[u])
hb(rt[u],rt[e[i].to],1,100000);
if(t[rt[u]].mx<=0)
ans[u]=0;
else
ans[u]=t[rt[u]].p;
if(!(--d[fa[u]]))
q.push(fa[u]);
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}
bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】的更多相关文章
- Bzoj 3307 雨天的尾巴(线段树合并+树上差分)
C. 雨天的尾巴 题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第 ...
- [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)
[BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...
- [Luogu5327][ZJOI2019]语言(树上差分+线段树合并)
首先可以想到对每个点统计出所有经过它的链的并所包含的点数,然后可以直接得到答案.根据实现不同有下面几种方法.三个log:假如对每个点都存下经过它的链并S[x],那么每新加一条路径进来的时候,相当于在路 ...
- BZOJ 3307: 雨天的尾巴( LCA + 线段树合并 )
路径(x, y) +z : u处+z, v处+z, lca(u,v)处-z, fa(lca)处-z, 然后dfs一遍, 用线段树合并. O(M log M + M log N). 复杂度看起来不高, ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
- BZOJ 3307 雨天的尾巴 (树上差分+线段树合并)
题目大意:给你一棵树,树上一共n个节点,共m次操作,每次操作给一条链上的所有节点分配一个权值,求所有节点被分配到所有的权值里,出现次数最多的权值是多少,如果出现次数相同就输出最小的. (我辣鸡bzoj ...
- bzoj 3307: 雨天的尾巴 线段树合并
题目大意: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.问完成所有发放后,每个点存放最多的是哪种物品. 题解: 首先我们为每一个节 ...
- bzoj 3307 雨天的尾巴
题目链接:传送门 题目大意:中文题,略 题目思路:网上有题解说是合并线段树的,但是太难蒟蒻不会,只能用树剖求解 如果不是树而是一维数组我们会怎么解? 当然是利用前缀和思想标记 (L) v+1,(R+1 ...
- [Vani有约会]雨天的尾巴(树上差分+线段树合并)
首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所有的救济粮 ...
随机推荐
- msp430入门编程27
msp430中C语言开发工具调试程序 msp430入门学习 msp430入门编程
- Pycharm工具配置记录
安装Pycharm工具后,常用配置方法记录: 1:开启“设置”快捷按钮 2:进入设置后,选择或添加python解释器 当然,python解释器需要提前安装好. 3:在设置里,配置默认模板 4 :自动更 ...
- hihocoder 1873 ACM-ICPC北京赛区2018重现赛 D Frog and Portal
http://hihocoder.com/problemset/problem/1873 时间限制:1000ms 单点时限:1000ms 内存限制:512MB 描述 A small frog want ...
- Android之怎样实现滑动页面切换【Fragment】
Fragment 页面切换不能滑动 所以对于listview 能够加入的左右滑动事件 .不会有冲突比如(QQ的好友列表的删除) Fragment 和viewpager 的差别 Viewpager ...
- CentOS 7下安装Logstash ELK Stack 日志管理系统(下)
修改防火墙,对外开放tcp/5601 [root@elk elk]# firewall-cmd --permanent --add-port=5601/tcpSuccess[root@elk elk] ...
- poj 1258 Agri-Net(Prim)(基础)
Agri-Net Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44487 Accepted: 18173 Descri ...
- python爬虫(二)--了解deque
队列-deque 有了上面一节的基础.当然你须要全然掌握上一节的全部方法,由于上一节的方法.在以下的教程中 会重复的用到. 假设你没有记住,请你返回上一节. http://blog.csdn.net/ ...
- 编写高质量代码:改善C#程序的157个建议
目录 前 言第一部分 语言篇第1章 基本语言要素 / 2建议1:正确操作字符串 / 2建议2:使用默认转型方法 / 6建议3:区别对待强制转型与as和is / 9建议4:TryParse比Parse好 ...
- OpenCV实践之路——Python的安装和使用
本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/50936076 微博:http ...
- 一起talk C栗子吧(第一百二十四回:C语言实例--内置宏)
各位看官们,大家好,上一回中咱们说的是显示变量和函数地址的样例,这一回咱们说的样例是:内置宏.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在编译程序的时候,假设有语法错误,编译器就 ...