题目

深绘里一直很讨厌雨天。

灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。

虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连

根拔起,以及田地里的粮食被弄得一片狼藉。

无奈的深绘里和村民们只好等待救济粮来维生。

不过救济粮的发放方式很特别。

首先村落里的一共有n 座房屋,并形成一个树状结构。然后救济粮分m 次发放,每次选择

两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮。

然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。

分析

相信大多数人都跟我一样,看到这道题,果断认为是树链剖分。

其实不然(我1.5h把熟练剖分打出来,以为能过50%。结果打错了,20%。然后。。。打暴力的人都是50%,#%……&*)。

我们注意到z<=10^9,那么的数据范围。

但是m<=100000,所以就先做个离散化。

。。。

接着用到个很神奇的东西,叫线段树合并。

对于树上的每一个节点开一棵线段树,记录该节点的每个z的数量以及某一段z的最大值。注意要动态开节点,否则会爆空间。

发现,如果要修改从
xy的路径,其实就是将x的z值加一,y的z值加一,lca(x,y)的z值减一以及fa[lca(x,y)]的z值减一(why?因为当线段树合并后从xlca(x,y)的路径上和从ylca(x,y)的路径上的每个节点的z值都加一,但lca(x,y)这个节点重复加了,那么就减掉。不过剩余的z值还会继续上传,所以在fa[lca(x,y)]**就把上传的z值减去)

合并操作

int mesh(int x,int y,int l,int r)
{
if(l==r)
{
tree[x].v+=tree[y].v;
return 0;
}
int mid=(l+r)/2;
if(tree[y].l)
{
if(!tree[x].l)
tree[x].l=tree[y].l;
else
mesh(tree[x].l,tree[y].l,l,mid);
}
if(tree[y].r)
{
if(!tree[x].r)
tree[x].r=tree[y].r;
else
mesh(tree[x].r,tree[y].r,mid+1,r);
}
tree[x].v=max(tree[tree[x].l].v,tree[tree[x].r].v);
}

当然,当所有的修改操作做完后才线段树合并,否则会超时。


#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
using namespace std;
struct trees
{
int l,r,v;
}tree[8000000];
struct read
{
int x,y,z;
}re[110000];
int next[201000],last[201000],to[201000],po,tot,n,m,g[200000][20],t[200000],deep[200000],f[200000],sum,ans[2000000];
bool cmp(read x,read y)
{
return x.z<y.z;
}
int bj(int x,int y)
{
next[++tot]=last[x];
last[x]=tot;
to[tot]=y;
}
int dg(int x)
{
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(j!=g[x][0])
{
deep[j]=deep[x]+1;
g[j][0]=x;
dg(j);
}
}
}
int prelca()
{
for(int j=1;j<=log2(n);j++)
{
for(int i=1;i<=n;i++)
{
g[i][j]=g[g[i][j-1]][j-1];
}
}
}
int lca(int x,int y)
{
if(deep[x]>deep[y])
{
x=x^y;
y=x^y;
x=x^y;
}
for(int i=log2(n);i>=0;i--)
{
if(deep[g[y][i]]>deep[x])
y=g[y][i];
}
if(deep[y]!=deep[x]) y=g[y][0];
for(int i=log2(n);i>=0;i--)
{
if(g[y][i]!=g[x][i])
{
y=g[y][i];
x=g[x][i];
}
}
if(x!=y) y=g[y][0];
return y;
}
int put(int v,int l,int r,int x,int y)
{
if(l==r)
{
tree[v].v+=y;
return 0;
}
int mid=(l+r)/2;
if(x<=mid)
{
if(!tree[v].l)
tree[v].l=++sum;
put(tree[v].l,l,mid,x,y);
}
else
{
if(!tree[v].r)
tree[v].r=++sum;
put(tree[v].r,mid+1,r,x,y);
}
tree[v].v=max(tree[tree[v].l].v,tree[tree[v].r].v);
}
int work(int x,int y,int z)
{
int lc=lca(x,y);
if(!f[x])
{
f[x]=++sum;
}
put(f[x],1,tot,z,1);
if(!f[y])
{
f[y]=++sum;
}
put(f[y],1,tot,z,1);
if(!f[lc])
{
f[lc]=++sum;
}
put(f[lc],1,tot,z,-1);
if(g[lc][0])
{
if(!f[g[lc][0]]) f[g[lc][0]]=++sum;
put(f[g[lc][0]],1,tot,z,-1);
}
}
int mesh(int x,int y,int l,int r)
{
if(l==r)
{
tree[x].v+=tree[y].v;
return 0;
}
int mid=(l+r)/2;
if(tree[y].l)
{
if(!tree[x].l)
tree[x].l=tree[y].l;
else
mesh(tree[x].l,tree[y].l,l,mid);
}
if(tree[y].r)
{
if(!tree[x].r)
tree[x].r=tree[y].r;
else
mesh(tree[x].r,tree[y].r,mid+1,r);
}
tree[x].v=max(tree[tree[x].l].v,tree[tree[x].r].v);
}
int find(int v,int l,int r)
{
if(l==r)
{
return l;
}
if(tree[tree[v].l].v==0 && tree[tree[v].r].v==0)
return 0;
int mid=(l+r)/2;
if(tree[tree[v].l].v>=tree[tree[v].r].v)
{
return find(tree[v].l,l,mid);
}
else
{
return find(tree[v].r,mid+1,r);
}
}
int merge(int x)
{
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(j!=g[x][0])
{
merge(j);
if(!f[x])
{
f[x]=++sum;
}
if(!f[j])
{
f[j]=++sum;
}
mesh(f[x],f[j],1,tot);
}
}
ans[x]=find(f[x],1,tot);
}
int main()
{
scanf("%d",&n);
scanf("%d",&m);
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
bj(x,y);
bj(y,x);
}
deep[1]=1;
dg(1);
prelca();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&re[i].x,&re[i].y,&re[i].z);
}
sort(re+1,re+m+1,cmp);
tot=0;
sum=0;
for(int i=1;i<=m;i++)
{
if(re[i].z==t[tot])
{
re[i].z=tot;
}
else
{
t[++tot]=re[i].z;
re[i].z=tot;
}
}
for(int i=1;i<=m;i++)
{
work(re[i].x,re[i].y,re[i].z);
}
merge(1);
for(int i=1;i<=n;i++)
{
if(!f[i])
{
f[i]=++sum;
}
printf("%d\n",t[ans[i]]);
}
}

【GDOI2014模拟】雨天的尾巴的更多相关文章

  1. BZOJ 3307: 雨天的尾巴( LCA + 线段树合并 )

    路径(x, y) +z : u处+z, v处+z, lca(u,v)处-z, fa(lca)处-z, 然后dfs一遍, 用线段树合并. O(M log M + M log N). 复杂度看起来不高, ...

  2. BZOJ_3307_雨天的尾巴_线段树合并+树上差分

    BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...

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

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

  4. 【BZOJ 3307】 3307: 雨天的尾巴 (线段树+树链剖分)

    3307: 雨天的尾巴 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 458  Solved: 210 Description N个点,形成一个树状结 ...

  5. 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告

    P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...

  6. [luogu4556]雨天的尾巴

    [luogu4556]雨天的尾巴 luogu 发现是一顿子修改然后再询问,那么把修改树上差分一下再线段树合并 但是... 如果你只有35分... https://www.luogu.org/discu ...

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

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

  8. Bzoj 3307 雨天的尾巴(线段树合并+树上差分)

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

  9. [bzoj3307]雨天的尾巴_线段树合并

    雨天的尾巴 bzoj-3307 题目大意:N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. ...

  10. 洛谷P4556 雨天的尾巴(线段树合并)

    洛谷P4556 雨天的尾巴 题目链接 题解: 因为一个点可能存放多种物品,直接开二维数组进行统计时间.空间复杂度都不能承受.因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一 ...

随机推荐

  1. 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_5 Mybatis中使用Dao实现类的执行过程分析-查询方法1

    继续运行testFindAll方法.把其他类的断点都删除掉. 只在这里加了断点,所以直接就跳转到这里了.RoutingStatementHandler里面的query方法 继续往下走,断点又回到了这里 ...

  2. charles抓包教程

    百度搜索下载charles 默认安装即可完成 1.双击charles.exe启动,我的是4.2.7版本.最好下载原版的不要去破解中文,会有不兼容 1.搜索该软件许可证书并输入即可长期使用 2.设置代理 ...

  3. C# 编写的webservice 怎样返回XML数据

    [WebMethod] public string GetXml() { string sConStr = ConfigurationManager.ConnectionStrings["c ...

  4. 杭州集训Day5

    下面是Day5的题目!(其实都咕了好几天了 100+70+40=210. T1 皇后 XY 的疑难 (1s 512MB) 1.1 题目描述 有一个n*n的王国城堡地图上,皇后XY喜欢看骑士之间的战斗, ...

  5. 命令行模式和Python交互模式的区别

    1.命令行模式: 在Windows开始菜单选择“命令提示符”,就进入到命令行模式,它的提示符类似C:\Users\>: 2.python交互模式 在命令行模式下敲命令python,就看到类似如下 ...

  6. JAVA日期时间相关库

    Java的日期时间库比较乱,同样一个Date在java.sql下定义,同时也在java.util下也定义了一遍,真不知道SUN是怎么想的. java8以后,java通过jsr310标准引入了一套符合I ...

  7. 【Linux-设备树】.dtb文件的反汇编

    在使用设备树时我们将**.dts文件利用dtc编译器编译为**.dtb文件. 在已知**.dtb文件的情况下我们有两种方法可以得到dts源码: 方法一:使用fdtdump工具进行反汇编 使用命令:ro ...

  8. CentOS7 安装SQLCMD

    1. Study From https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-setup-tools?view=sql-serve ...

  9. STM32 晶振 系统时钟8MHZ和72Mhz的原因

    首先问题描述: 1.自己画的板子和淘宝买的最小系统板 系统时钟不一致,自己画的是8Mhz,HSE失败:最小系统板72Mhz 2.最小系统板在程序1运行仿真的时候,查看peripherals->P ...

  10. Java8---函数式编程-示例

    // Java8函数式编程示例—(Predicate.Stream.Optional) https://blog.csdn.net/weixin_41950473/article/details/84 ...