浅谈线段树合并:https://www.cnblogs.com/AKMer/p/10251001.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=3307

每次放物资就树上差分一下,然后用线段树维护差分值\(max\),自底向上合并统计答案即可。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(nlogn)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std; const int maxn=1e5+5; int n,m,tot,cnt;
int f[maxn][18];
int rt[maxn],dep[maxn],ans[maxn];
int X[maxn],Y[maxn],Z[maxn],tmp[maxn];
int now[maxn],pre[maxn*2],son[maxn*2]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} namespace T {
int tot;
int ls[maxn*50],rs[maxn*50];
struct tree_node {int cnt,id;}tree[maxn*50]; tree_node calc(tree_node a,tree_node b) {
if(a.cnt>b.cnt)return a;
if(a.cnt<b.cnt)return b;
if(a.id<b.id)return a;
return b;
} void update(int p) {
tree[p]=calc(tree[ls[p]],tree[rs[p]]);
if(!tree[p].cnt)tree[p].id=0;
} void change(int &p,int l,int r,int pos,int v) {
if(!p)p=++tot;
if(l==r) {
if(!tree[p].id)tree[p].id=l;
tree[p].cnt+=v;return;
}
int mid=(l+r)>>1;
if(pos<=mid)change(ls[p],l,mid,pos,v);
else change(rs[p],mid+1,r,pos,v);
update(p);
} int merge(int a,int b) {
if(!a||!b)return a+b;
if(!ls[a]&&!rs[a]&&!ls[b]&&!rs[b]) {
tree[a].cnt+=tree[b].cnt;
return a;
}
ls[a]=merge(ls[a],ls[b]);
rs[a]=merge(rs[a],rs[b]);
update(a);return a;
}
} void add(int a,int b) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b;
} void dfs(int fa,int u) {
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;i<18;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(v!=fa)dfs(u,v);
} void make_ans(int fa,int u) {
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(v!=fa)make_ans(u,v),rt[u]=T::merge(rt[u],rt[v]);
if(!T::tree[rt[u]].cnt)ans[u]=0;//这里要加特判是因为有可能线段树只有一个结点并且加成了0
else ans[u]=T::tree[rt[u]].id;
} int lca(int a,int b) {
if(dep[a]<dep[b])swap(a,b);
for(int i=17;~i;i--)
if(dep[f[a][i]]>=dep[b])
a=f[a][i];
if(a==b)return a;
for(int i=17;~i;i--)
if(f[a][i]!=f[b][i])
a=f[a][i],b=f[b][i];
return f[a][0];
} int main() {
n=read(),m=read();
for(int i=1;i<n;i++) {
int a=read(),b=read();
add(a,b),add(b,a);
}
dfs(0,1);
for(int i=1;i<=m;i++)
X[i]=read(),Y[i]=read(),tmp[i]=Z[i]=read();
sort(tmp+1,tmp+m+1);
cnt=unique(tmp+1,tmp+m+1)-tmp-1;
for(int i=1;i<=m;i++)
Z[i]=lower_bound(tmp+1,tmp+cnt+1,Z[i])-tmp;
for(int i=1;i<=m;i++) {
int x=X[i],y=Y[i],z=Z[i];
int fa=lca(x,y);
T::change(rt[x],1,cnt,z,1);
T::change(rt[y],1,cnt,z,1);
T::change(rt[fa],1,cnt,z,-1);
T::change(rt[f[fa][0]],1,cnt,z,-1);
}
make_ans(0,1);
for(int i=1;i<=n;i++)
printf("%d\n",tmp[ans[i]]);
return 0;
}

BZOJ3307:雨天的尾巴的更多相关文章

  1. [BZOJ3307] 雨天的尾巴(树上差分+线段树合并)

    [BZOJ3307] 雨天的尾巴(树上差分+线段树合并) 题面 给出一棵N个点的树,M次操作在链上加上某一种类别的物品,完成所有操作后,要求询问每个点上最多物品的类型. N, M≤100000 分析 ...

  2. [bzoj3307]雨天的尾巴_线段树合并

    雨天的尾巴 bzoj-3307 题目大意:N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. ...

  3. BZOJ3307 雨天的尾巴

    首先考虑序列怎么做... 只要把操作差分了,记录在每个点上 然后维护一棵权值线段树,表示每个颜色出现的次数,支持单点修改和查询最大值操作 只要把序列扫一遍就好了,时间复杂度$O(n + m*logZ) ...

  4. BZOJ3307雨天的尾巴——线段树合并

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来N ...

  5. [洛谷P4556][BZOJ3307]雨天的尾巴-T3订正

    线段树合并+树上差分 题目链接(···) 「简单」「一般」——其实「一般」也只多一个离散化 考试时想法看>这里< 总思路:先存所有的操作,离散化,然后用树上差分解决修改,用权值线段树维护每 ...

  6. [BZOJ3307]:雨天的尾巴(LCA+树上差分+权值线段树)

    题目传送门 题目描述: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式: 第一 ...

  7. bzoj3307 雨天的尾巴 题解(线段树合并+树上差分)

    Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后,每个点存放最多的是哪种物品. Input ...

  8. bzoj3307雨天的尾巴(权值线段树合并/DSU on tree)

    题目大意: 一颗树,想要在树链上添加同一物品,问最后每个点上哪个物品最多. 解题思路: 1.线段树合并 假如说物品数量少到可以暴力添加,且树点极少,我们怎么做. 首先在一个树节点上标记出哪些物品有多少 ...

  9. bzoj3307 雨天的尾巴题解及改题过程(线段树合并+lca+树上差分)

    题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第一行数字N,M接下 ...

  10. [BZOJ3307] 雨天的尾巴-----------------线段树进阶

    虽然是个板子,但用到了差分思想. Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最 ...

随机推荐

  1. 几种动态调用js函数方案的性能比较

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. <%%>与<scriptrunat=server>,<%=%>与<%#%>的区别(转)

    这些东西都是asp.net前台页面与后台代码交互过程中经常使用的,它们之间有的非常相似,又有一些不同.对比学习下,看看他们之间的联系与区别. 首先看<%%>与<scriptrunat ...

  3. CMD命令获取电脑所有连接过的WiFi密码

    cmd中输入命令:for /f "skip=9 tokens=1,2 delims=:" %i in ('netsh wlan show profiles') do  @echo ...

  4. AFN errorCode对应的状态码

    转 http://blog.csdn.NET/wangyanchang21/article/details/50932191 在很多时候都会遇到错误, 还会带有一些 Error Code , 比如在各 ...

  5. data standardization

    import random import numpy as np l, num, gen_min_, gen_max_ = [], 100, 1, 200 l = [random.randint(ge ...

  6. spark0.9.0安装

    利用周末的时间安装学习了下最近很火的Spark0.9.0(江湖传言,要革hadoop命,O(∩_∩)O),并体验了该框架下的机器学习包MLlib(spark解决的一个重点就是高效的运行迭代算法),下面 ...

  7. bd存储

    var sessionData = new Array();var setSessionData=function(key,val){ if(sessionStorage){ sessionStora ...

  8. python基础2 ---python数据类型一

    python的数据类型 一.什么是数据类型以及数据类型的分类 1.数据类型的定义:python使用对象模型来存储数据,每一个数据类型都有一个内置的类,每新建一个数据,实际就是在初始化生成一个对象,即所 ...

  9. Linux ~ termios 串口编程

    ermios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口,通过设置termios类型的数据结构中的值和使用一小 组函数调用,你就可以对终端接口进行控制. 可以被调整来影 ...

  10. STM32大文件分块校验CRC

    一.CRC校验的使用    STM32内置CRC计算单元,节约了软件计算的时间.在软件开发中,可以为firm追加4字节的CRC校验码到生成的BIN文件最后位置,这个CRC码就是全部代码区域数据的CRC ...