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. 如何发布一个自定义Node.js模块到NPM(详细步骤,附Git使用方法)

    咱们闲话不多说,直接开始! 由于我从没有使用过MAC,所以我不保证本文中介绍的操作与MAC一致. 文章开始我先假定各位已经在window全局安装了Node.js,下面开始进行详细步骤介绍: 本文本着, ...

  2. GridControl详解(六)样式设置

    表格样式:全局设置 例子: 例子: 列样式:只作用于当前的列 通用样式:外观设定 注意:样式设定都是相同的,Appearance前缀.

  3. [php]unset函数

    unset($var); 释放一个变量空间 unset($var1, $var2...);释放多个变量空间 unset(var['数组元素内容']);释放数组元素 注意: 1.在函数内部释放全局变量和 ...

  4. 【CODEVS】1033 蚯蚓的游戏问题

    [算法]网络流-最小费用最大流(费用流) [题解]与方格取数2类似 在S后添加辅助点S_,限流k 每条边不能重复走,限流1 #include<cstdio> #include<alg ...

  5. js获得页面鼠标位置

    1.客户区坐标位置:clientX,clientY 鼠标相对于在当前页面可视范围左上角的位置 2.页面坐标位置:pageX,pageY 鼠标相对于页面左上角的位置(受滑动等影响,例如pageY=cli ...

  6. hihoCoder #1175 : 拓扑排序·二

    题目链接:http://hihocoder.com/problemset/problem/1175 代码实现如下: #include <queue> #include <cstdio ...

  7. favico.js笔记

    1. favicon.js是什么 一个js库可以使用徽标.图像.视频等来设置网页的favicon,即网页标题栏上的小图标. 2. 如何使用 2.1 使用徽标 basic demo: <!DOCT ...

  8. 树的直径(两个bfs)

    题目链接:https://cn.vjudge.net/problem/POJ-2631 树的直径:树中的最长链 具体思路:随便找一个点bfs,然后找到最长的链,然后再以找到的点作为起点进行bfs,然后 ...

  9. Java跨域问题的处理

    1,JavaScript由于安全性方面的考虑,不允许页面跨域调用其他页面的对象,那么问题来了,什么是跨域问题? 答:这是由于浏览器同源策略的限制,现在所有支持JavaScript的浏览器都使用了这个策 ...

  10. sendEmail实现邮件报警

    安装 wget http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz 或者点击下载 tar -xf sen ...