3307: 雨天的尾巴

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 458  Solved: 210

Description

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个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0

Sample 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 50

Sample Output

87
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
50

1<=N,M<=100000
1<=a,b,x,y<=N
1<=z<=10^9

HINT

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 ;
}

好像Po姐有更好的方法?

2017-03-27 16:10:51

【BZOJ 3307】 3307: 雨天的尾巴 (线段树+树链剖分)的更多相关文章

  1. [Vani有约会]雨天的尾巴 线段树合并

    [Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...

  2. 【BZOJ3307】雨天的尾巴 线段树合并

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

  3. 【BZOJ3307】雨天的尾巴 题解(树链剖分+树上差分)

    题目链接 题目大意:给定一颗含有$n$个结点的树,每次选择两个结点$x$和$y$,对从$x$到$y$的路径上发放一带$z$类型的物品.问完成所有操作后每个结点发放最多的时哪种物品. 普通的树链剖分貌似 ...

  4. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  5. bzoj 3307: 雨天的尾巴 线段树合并

    题目大意: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.问完成所有发放后,每个点存放最多的是哪种物品. 题解: 首先我们为每一个节 ...

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

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

  7. 洛谷P4556 雨天的尾巴 线段树

    正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...

  8. 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)

    题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...

  9. P4556 雨天的尾巴 线段树合并

    使用线段树合并,每个节点维护一棵权值线段树,下标为救济粮种类,区间维护数量最多的救济粮编号(下标).所以每个节点答案即为\(tre[rot[x]]\). 然后运用树上点的差分思想,对于分发路径\(u, ...

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

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

随机推荐

  1. JQuery的链式编程,隐式迭代是啥意思?

    链式编程 1.好处 "一句话,链式编程可以省去很多重复的代码." 这话什么意思呢?举个例子. /*设置obj对象的两个属性*/ //普通做法是这样的 obj.name = '小明' ...

  2. ueditor和thinkphp框架整合修改版

    基于tp官网上的一篇文章修改的  因为tp中所有目录其实都是性对于入口文件的 在原来的基础上略做修改后 已经做到 无论项目放在www下的任何位置 图片在编辑器中回填后都能正常显示! http://fi ...

  3. python基础之内置异常对象

    前言 什么叫异常?简单来说就是程序运行发生了预计结果之外的情况从而导致程序无法正常运行.而python解释器将一些常见的异常情况在它发生时打包成一个异常对象,我们可以通过捕捉这些异常对象从而进行处理, ...

  4. django框架之中间件

    中间件简介 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在djang ...

  5. HZ与Jiffies

    2.4 内核定时器 内核中许多部分的工作都高度依赖于时间信息.Linux内核利用硬件提供的不同的定时器以支持忙等待或睡眠等待等时间相关的服务.忙等待时,CPU 会不断运转.但是睡眠等待时,进程将放弃C ...

  6. 码源中国.gitignore忽略文件配置

    码源中国.gitignore忽略文件配置 ## Ignore Visual Studio temporary files, build results, and ## files generated ...

  7. 003_循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别

    表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...

  8. Ubuntu vi 上下左右变ABCD问题解决方法

    ---恢复内容开始--- 错误问题:vi上下左右键显示为ABCD的问题 解决方法: 只要依次执行以下两个命令即可完美解决Ubuntu下vi编辑器方向键变字母的问题. 一.执行命令 sudo apt-g ...

  9. Percona XtraDB Cluster(PXC)-高可用架构设计说明

    Mycat+PXC高可用集群 一.架构图 架构说明: 1.mysql 集群高可用部分: l 针对业务场景选用Percona XtraDB Cluter(PXC)复制集群.两个片集群 PXC-dataN ...

  10. Effective STL 笔记: Item 6--Be alert for C++'s most vexing parse

    假设有个文件里面记录的一系列的 int 值,现在我们想把这些数值存到一个 List 里面,结合 Item 5, 我们可能会写出下面的代码: ifstream dataFile("ints.d ...