【BZOJ 3307】 3307: 雨天的尾巴 (线段树+树链剖分)
3307: 雨天的尾巴
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 458 Solved: 210Description
N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。Input
第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题Output
输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0Sample Input
20 50
8 6
10 6
18 6
20 10
7 20
2 18
19 8
1 6
14 20
16 10
13 19
3 14
17 18
11 19
4 11
15 14
5 18
9 10
12 15
11 14 87
12 1 87
14 3 84
17 2 36
6 5 93
17 6 87
10 14 93
5 16 78
6 15 93
15 5 16
11 8 50
17 19 50
5 4 87
15 20 78
1 17 50
20 13 87
7 15 22
16 11 94
19 8 87
18 3 93
13 13 87
2 1 87
2 6 22
5 20 84
10 12 93
18 12 87
16 10 93
8 17 93
14 7 36
7 4 22
5 9 87
13 10 16
20 11 50
9 16 84
10 17 16
19 6 87
12 2 36
20 9 94
9 2 84
14 1 94
5 5 94
8 17 16
12 8 36
20 17 78
12 18 50
16 8 94
2 19 36
10 18 36
14 19 50
4 12 50Sample Output
87
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
501<=N,M<=100000
1<=a,b,x,y<=N
1<=z<=10^9HINT
Source
【分析】
什么时候样例这样良心。。
按照z排序,然后树剖标记一下区间,然后统计个数相同的区间add到线段树里面求min,这些区间个数不会超过3*mlogn,因为树剖区间logn个,一个新的区间最多只会把原来的分割成3部分。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 100010 int mymax(int x,int y) {return x>y?x:y;} struct node
{
int l,r,lc,rc,mx,id;
int lazy,lad;
}tr[Maxn*]; struct nnode{int x,y,z;}t[Maxn],tt[Maxn],t3[Maxn*];
int first[Maxn],len; bool cmp(nnode x,nnode y) {return x.z<y.z;}
bool cmp2(nnode x,nnode y) {return x.x<y.x;} void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].z=first[x];first[x]=len;
} int fa[Maxn],son[Maxn],tp[Maxn],sm[Maxn],dep[Maxn];
void dfs1(int x,int ff)
{
dep[x]=dep[ff]+;
fa[x]=ff;sm[x]=;son[x]=;
for(int i=first[x];i;i=t[i].z) if(t[i].y!=ff)
{
int y=t[i].y;
dfs1(y,x);
sm[x]+=sm[y];
if(son[x]==||sm[y]>sm[son[x]]) son[x]=y;
}
} int cnt,dfn[Maxn];
void dfs2(int x,int tpp)
{
dfn[x]=++cnt;tp[x]=tpp;
if(son[x]) dfs2(son[x],tpp);
for(int i=first[x];i;i=t[i].z) if(t[i].y!=fa[x]&&t[i].y!=son[x])
{
int y=t[i].y;
dfs2(y,y);
}
} int tot=;
int build(int l,int r)
{
int x=++tot;
tr[x].l=l;tr[x].r=r;tr[x].mx=;tr[x].lazy=;
if(l!=r)
{
int mid=(l+r)>>;
tr[x].lc=build(l,mid);
tr[x].rc=build(mid+,r);
}
else tr[x].lc=tr[x].rc=;
return x;
} void upd(int x)
{
if(tr[x].lazy==) return;
int lc=tr[x].lc,rc=tr[x].rc;
if(tr[x].lazy>tr[x].mx) tr[x].mx=tr[x].lazy,tr[x].id=tr[x].lad;
if(tr[x].l==tr[x].r) {tr[x].lazy=;return;}
if(tr[x].lazy>tr[lc].lazy) tr[lc].lazy=tr[x].lazy,tr[lc].lad=tr[x].lad;
if(tr[x].lazy>tr[rc].lazy) tr[rc].lazy=tr[x].lazy,tr[rc].lad=tr[x].lad;
tr[x].lazy=;
} void change(int x,int l,int r,int y,int id)
{
if(tr[x].l==l&&tr[x].r==r)
{
if(y>tr[x].lazy) tr[x].lazy=y,tr[x].lad=id;
upd(x);return;
}
upd(x);
int mid=(tr[x].l+tr[x].r)>>;
if(r<=mid) change(tr[x].lc,l,r,y,id);
else if(l>mid) change(tr[x].rc,l,r,y,id);
else {change(tr[x].lc,l,mid,y,id);change(tr[x].rc,mid+,r,y,id);}
if(tr[tr[x].lc].mx>=tr[tr[x].rc].mx) tr[x].mx=tr[tr[x].lc].mx,tr[x].id=tr[tr[x].lc].id;
else tr[x].mx=tr[tr[x].rc].mx,tr[x].id=tr[tr[x].rc].id;
} int query(int x,int y)
{
upd(x);
if(tr[x].l==tr[x].r) return tr[x].id;
int mid=(tr[x].l+tr[x].r)>>;
if(y<=mid) return query(tr[x].lc,y);
return query(tr[x].rc,y);
} int tl;
int add(int x,int y)
{
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
t3[++tl].x=dfn[tp[x]];t3[tl].y=;
t3[++tl].x=dfn[x]+;t3[tl].y=-;
x=fa[tp[x]];
}
if(dep[x]>dep[y]) swap(x,y);
t3[++tl].x=dfn[x];t3[tl].y=;
t3[++tl].x=dfn[y]+;t3[tl].y=-;
} void ffind(int st,int ed,int id)
{
tl=;
for(int i=st;i<=ed;i++)
{
add(tt[i].x,tt[i].y);
}
sort(t3+,t3++tl,cmp2);
int nw=;
for(int i=;i<tl;i++)
{
nw+=t3[i].y;
if(t3[i].x!=t3[i+].x&&nw!=)
{
// printf("%d %d %d\n",t3[i].x,t3[i+1].x-1,nw);
change(,t3[i].x,t3[i+].x-,nw,id);
}
}
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
len=;
memset(first,,sizeof(first));
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
dep[]=;dfs1(,);
cnt=;dfs2(,);
for(int i=;i<=m;i++) scanf("%d%d%d",&tt[i].x,&tt[i].y,&tt[i].z);
sort(tt+,tt++m,cmp);
build(,n);
int st=;
for(int i=;i<=m;i++)
{
if(i==m||tt[i].z!=tt[i+].z)
{
ffind(st,i,tt[i].z);
st=i+;
}
}
for(int i=;i<=n;i++) printf("%d\n",query(,dfn[i]));
return ;
}
2017-03-27 16:10:51
【BZOJ 3307】 3307: 雨天的尾巴 (线段树+树链剖分)的更多相关文章
- [Vani有约会]雨天的尾巴 线段树合并
[Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...
- 【BZOJ3307】雨天的尾巴 线段树合并
[BZOJ3307]雨天的尾巴 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多 ...
- 【BZOJ3307】雨天的尾巴 题解(树链剖分+树上差分)
题目链接 题目大意:给定一颗含有$n$个结点的树,每次选择两个结点$x$和$y$,对从$x$到$y$的路径上发放一带$z$类型的物品.问完成所有操作后每个结点发放最多的时哪种物品. 普通的树链剖分貌似 ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- bzoj 3307: 雨天的尾巴 线段树合并
题目大意: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.问完成所有发放后,每个点存放最多的是哪种物品. 题解: 首先我们为每一个节 ...
- BZOJ3307雨天的尾巴——线段树合并
题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入 第一行数字N,M接下来N ...
- 洛谷P4556 雨天的尾巴 线段树
正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- P4556 雨天的尾巴 线段树合并
使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u, ...
- [BZOJ3307] 雨天的尾巴-----------------线段树进阶
虽然是个板子,但用到了差分思想. Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最 ...
随机推荐
- React-music 全家桶项目
React-Music 全家桶项目 一.简介 该项目是基于React全家桶开发的一个音乐播放器,技术栈采用:Webpack + React + React-redux + React-router + ...
- Master of Phi (欧拉函数 + 积性函数的性质 + 狄利克雷卷积)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6265 题目大意:首先T是测试组数,n代表当前这个数的因子的种类,然后接下来的p和q,代表当前这个数的因 ...
- hdu 2063 过山车 二分匹配(匈牙利算法)
简单题hdu2063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 过山车 Time Limit: 1000/1000 MS (Java/Ot ...
- pycharm设置字体大小
pycharm 是很好的一个IDE,在windows下,和macOS下,都能很好的运行.唯一缺点是启动慢. 默认字体太小,在mac下,需要瞪大24K氪金狗眼才能看清. 为了保护好眼睛,我们需要把字体调 ...
- 多维尺度变换MDS(Multidimensional Scaling)
流形学习(Manifold Learning)是机器学习中一大类算法的统称,流形学习是非线性的降维方法(an approach to non-linear dimensionality reducti ...
- 二. Jmeter--参数化
1. 新建一个txt文件,输入些数据, 一行有四个数据,用逗号分隔. 保存的时候Encoding选择Unicode 2.添加一个Thread Group, 然后添加一个CSV Data Set Con ...
- linux ip白名单、防火墙白名单 设置
http://blog.csdn.net/catoop/article/details/50476099 登录信息在 /var/log/secure linux ip白名单 配置文件:/etc/hos ...
- python并发编程之multiprocessing进程(二)
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. 系列文章 python并发编程之threading线程(一) python并 ...
- C语言回调函数总结
/* Main program ---calls--> Library function ---calls--> Callback funtion */ #include <stdi ...
- elk系列2之multiline模块的使用【转】
preface 上回说道了elk的安装以及kibana的简单搜索语法,还有logstash的input,output的语法,但是我们在使用中发现了一个问题,我们知道,elk是每一行为一个事件,像Jav ...