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. 【BZOJ】1537: [POI2005]Aut- The Bus

    [算法]DP+线段树求区间max(二维偏序) [题解] 状态转移方程:f[i]=max(f[j]+v[i]),x[j]<x[i]&&y[j]<y[i]. 观察j的条件限制显 ...

  2. Lithium中关键特性更新

    Lithium中关键特性更新 1. Lithium特性更新概述 Lithium相对于Helium更新特性共27项,其中原有特性提升或增强13项,新增特性14项,如下表所示 特性类型 相对于Helium ...

  3. ubuntu14.04安装使用NviDIA显卡驱动

    想给自己的ubuntu换N卡驱动的原因: 一方面,由于自己电脑在编译源代码8线程全开(make -j8)时,CPU温度呼呼涨到八九十度,从而常常导致系统保护自动关机,让人有点不爽.网上有说ubuntu ...

  4. 浅析linux内核中timer定时器的生成和sofirq软中断调用流程(转自http://blog.chinaunix.net/uid-20564848-id-73480.html)

    浅析linux内核中timer定时器的生成和sofirq软中断调用流程 mod_timer添加的定时器timer在内核的软中断中发生调用,__run_timers会spin_lock_irq(& ...

  5. 34.Find First and Last Position of Element in Sorted Array---头条面试题、《剑指offer》38

    题目链接 题目大意:找出一串升序数组中target值的起始下标和结束下标值,如果不存在则返回{-1,-1}. 解法一:用二分查找,找到数组中的target,然后找其左边和右边的target下标值.代码 ...

  6. 安装 Xamarin for Visual Studio

    总得来说,Xamarin 有“联网自动安装”和“手动安装”两种方式. 说明:本文涉及得资源链接都是官网的,同时,在 我的网盘 也有相关备份. 现在,我就以 Windows 为例来大概说明……(-=-我 ...

  7. csu 1803(余数分类)

    1803: 2016 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 565  Solved: 364[Submit][Status][Web Board ...

  8. scala学习7--class、object、trait

    scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用不同的表达方式,cla ...

  9. Jmeter----请求的reponse结果中的某个参数作为JDBC Request的查询条件

    一.前言 数据库连接成功,若不会的查看:https://www.cnblogs.com/syw20170419/p/9832402.html 二.需求 将登录账号12608523691,接口的repo ...

  10. 关于HTML&CSS的笔记

    最近在看Jon Duckett的HTML&CSS一书(http://book.douban.com/subject/6585090/),书的排版和讲解方式很不错,并且有许多其他教学材料遗漏的关 ...