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. 为什么 .NET 会被叫做 .NET?

    微软开发.NET Framework是在20世纪90年代后期,最初是叫做“下一代Windows服务”(Next Generation Windows Services 简称 NGWS). 那么为什么微 ...

  2. js_beautifier && css_beautifier for emeditor

    // // Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier // written by Einar Li ...

  3. matlab前景分割

    用最简单的差分法实现了一下前景分割.使用的mall数据集. 思路是这样的:首先设定一个队列的长度,若读取的图片张数少于队列长度则以当前读取到的图片做平均.否则则以队列中的图片做平均. 这样之后和当前图 ...

  4. python基础之常用内置函数

    前言 python有许多内置的函数,它们定义在python的builtins模块,在python的代码中可以直接使用它们. 常用的内置函数 类型转换 int python的整数类型都是int类型的实例 ...

  5. C# 获取mp3文件的歌曲时间长度

    添加命名空间:    using Shell32;    using System.Text.RegularExpressions;添加引用:COM组件的Microsoft Shell Control ...

  6. URAL题解二

    URAL题解二 URAL 1082 题目描述:输出程序的输入数据,使得程序输出"Beutiful Vasilisa" solution 一开始只看程序的核心部分,发现是求快排的比较 ...

  7. Jmeter-----图形监控

    1.下载插件地址:https://jmeter-plugins.org/downloads/old/ 1)JmeterPlugins-Standard 插件:将JMeterPlugins.jar放到J ...

  8. day4 递归原理及解析

    递归 递归是一种调用自身的方法,在函数执行过程中重复不断的调用自身的过程,递归的规模每次都要缩小,一般前一步的程序作为后一步的参数.但是必须有递归结束条件. 递归算法是一种直接或者间接地调用自身算法的 ...

  9. Cookie机制和Session机制

    1. cookie 1. Cookie 是在HTTP协议下,服务器或脚本可以维护客户工作站上信息的一种方式.Cookie 是由 Web服务器保存在用户浏览器(客户端)上的小文本文件(内容通常经过加密) ...

  10. html 条件注释判断浏览器版本<!--[if lt IE 9]>

    <!--[if lte IE 8]><script>window.location.href='http://support.dmeng.net/upgrade-your-br ...