【bzoj4538】[Hnoi2016]网络
我们考虑树剖,线段树上维护一个堆,保存不经过该段区间的路径的权值。
对于一条路径我们将对于线段树中的区间提取出来,在对于线段树中进行修改。也就是在堆中插入或删除。
对于一次询问,只要找到包含该点的线段中堆顶权值最大的就行了。
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std; typedef long long LL; #define N 200010 struct data
{
int l,r;
}q[N]; struct edge
{
int s,to,next;
}e[N<<];
int head[N<<];
int cnt; int dep[N],siz[N],son[N],top[N],pos[N];
int fa[N][],val[N<<]; bool vis[N]; int n,m;
int ans,res,num; int askd; struct cmp
{
bool operator() (int a,int b)
{
return val[a]<val[b];
}
}; priority_queue<int,vector<int>,cmp> Q[N<<]; bool cmp(data a,data b)
{
return a.l<b.l;
} void link(int x,int y)
{
e[++cnt]=(edge){x,y,head[x]};
head[x]=cnt;
} void dfs(int x)
{
siz[x]=;
son[x]=;
for (int i=head[x];i;i=e[i].next)
{
int t=e[i].to;
if (t!=fa[x][])
{
dep[t]=dep[x]+;
fa[t][]=x;
dfs(t);
siz[x]+=siz[t];
if (siz[t]>siz[son[x]])
son[x]=t;
}
}
} void dfs2(int x,int cha)
{
pos[x]=++res;
top[x]=cha;
if (son[x])
dfs2(son[x],cha);
for (int i=head[x];i;i=e[i].next)
{
int t=e[i].to;
if (t!=fa[x][] && t!=son[x])
dfs2(t,t);
}
} void build_lca()
{
for (int j=;j<=;j++)
for (int i=;i<=n;i++)
if (fa[i][j-])
fa[i][j]=fa[fa[i][j-]][j-];
} int lca(int x,int y)
{
if (dep[x]<dep[y])
swap(x,y);
int t=dep[x]-dep[y];
for (int i=;i>=;i--)
if (t & (<<i))
x=fa[x][i];
if (x==y)
return x;
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][];
} void add(int nowl,int nowr,int now,int l,int r,int d)
{
if (l<=nowl && nowr<=r)
{
Q[now].push(d);
return ;
}
int mid=(nowl+nowr)>>;
if (l<=mid)
add(nowl,mid,now<<,l,r,d);
if (r>=mid+)
add(mid+,nowr,now<<|,l,r,d);
} void query(int nowl,int nowr,int now,int d)
{
while (!Q[now].empty())
{
int k=Q[now].top();
if (vis[k])
Q[now].pop();
else
{
num=max(num,val[k]);
break;
}
}
if (nowl==nowr)
return ;
int mid=(nowl+nowr)>>;
if (d<=mid)
query(nowl,mid,now<<,d);
else
query(mid+,nowr,now<<|,d);
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
link(x,y);
link(y,x);
}
dep[]=;
dfs();
dfs2(,);
build_lca();
for (int i=;i<=m;i++)
{
scanf("%d",&askd);
if (askd==)
{
scanf("%d%d%d",&x,&y,&val[i]);
int w=,z=lca(x,y);
while (dep[top[x]]>dep[z])
{
q[++w]=(data){pos[top[x]],pos[x]};
x=fa[top[x]][];
}
while (dep[top[y]]>dep[z])
{
q[++w]=(data){pos[top[y]],pos[y]};
y=fa[top[y]][];
}
if (x!=z)
q[++w]=(data){pos[z],pos[x]};
else if (y!=z)
q[++w]=(data){pos[z],pos[y]};
else
q[++w]=(data){pos[z],pos[z]};
q[++w]=(data){n+,n+};
sort(q+,q+w+,cmp);
for (int j=;j<=w;j++)
if (q[j-].r<q[j].l-)
add(,n,,q[j-].r+,q[j].l-,i);
}
else if (askd==)
{
scanf("%d",&x);
vis[x]=;
}
else
{
scanf("%d",&x);
num=-;
query(,n,,pos[x]);
printf("%d\n",num);
}
}
return ;
}
【bzoj4538】[Hnoi2016]网络的更多相关文章
- BZOJ4538 HNOI2016网络(树链剖分+线段树+堆/整体二分+树上差分)
某两个点间的请求只对不在这条路径上的询问有影响.那么容易想到每次修改除该路径上的所有点的答案.对每个点建个两个堆,其中一个用来删除,线段树维护即可.由于一条路径在树剖后的dfs序中是log个区间,所以 ...
- BZOJ4538 : [Hnoi2016]网络
求出这棵树的dfs序,对于一条链$u-v$,假设$st[u]\leq st[v]$,那么一条链不经过点$x$当且仅当它满足下面任意一个条件: 1.$st[v]<st[x]$ 2.$st[u]&g ...
- 2019.01.13 bzoj4538: [Hnoi2016]网络(树链剖分)
传送门 树链剖分一眼题. 题意简述: 给定一棵树,有三种操作: 加入一条路径 删除一条已加入的路径 询问不过一个点x的路径的最大值. 思路: 直接树链剖分维护答案. 因为询问的事不过点xxx的最大值, ...
- BZOJ4538:[HNOI2016]网络(树链剖分,堆)
Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做 一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有 ...
- 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组
[BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...
- BZOJ 4538: [Hnoi2016]网络 [整体二分]
4538: [Hnoi2016]网络 题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值 考虑二分 整体二分最大权值,如果\(k \in [mid+1, ...
- 【LG3250】[HNOI2016]网络
[LG3250][HNOI2016]网络 题面 洛谷 题解 30pts 对于\(m\leq 2000\),直接判断一下这个个点是否断掉一个交互,没断掉的里面取\(max\)即可,复杂度\(O(m^2\ ...
- 4538: [Hnoi2016]网络
4538: [Hnoi2016]网络 链接 分析: 整体二分. 对于一次操作,可以二分一个答案mid,判断权值大于mid的路径是否全部经过这个点.如果是 ,那么这次询问的答案在[l,mid-1]之间, ...
- [HNOI2016]网络 树链剖分,堆
[HNOI2016]网络 LG传送门 表示乱搞比正解难想. 整体二分很好想吧. 但是为了好写快乐,我们选择三个\(\log\)的乱搞. 先树剖,线段树套堆维护区间最大值.对于一次修改,如果是插入,就把 ...
- Luogu-3250 [HNOI2016]网络
Luogu-3250 [HNOI2016]网络 题面 Luogu-3250 题解 CDQ分治...这个应该算是整体二分吧 二分重要度,按照时间从小到大加入大于重要度的边 对于一个询问,如果经过这个点的 ...
随机推荐
- python appium自动化,走过的坑
使用的夜神模拟器,使用android5.1.1 第一坑:使用的android7.1.2,刚开始写好了登录的代码,需要的是滑屏进入到登录界面,结果运行的时候,没有自动滑屏就报错:因为运行时,报了一个进程 ...
- pycharm connect to mysql
1.download mysql installer community 5.7.20 https://dev.mysql.com/downloads/file/?id=473605 or 链接:ht ...
- PHP实现微信第三方登录的方法
本文实例讲述了PHP版微信第三方实现一键登录及获取用户信息的方法.分享给大家供大家参考,具体如下: 注意,要使用微信在第三方网页登录是需要“服务号”才可以哦,所以必须到官方申请 一开始你需要进入微信公 ...
- Volume 1. Maths - Misc
113 - Power of Cryptography import java.math.BigInteger; import java.util.Scanner; public class Main ...
- 配置python3 项目环境
安装python3 安装仓库软件 sudo apt-get install software-properties-common python-software-properties 添加仓库 sud ...
- Python中的列表(6)
列表切片 如何拿到列表中的部分元素,Python 引入了 “切片” 的概念. 上代码: words = ['a','b','c','d'] print(words[0:3]) console: 冒号( ...
- LeetCode(59)SPiral Matrix II
题目 Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. F ...
- MFC对话框使用CPrintDialog实现打印,指定打印机、后台打印
推荐下 不错. 对话框打印,网上一搜一大堆,基本分2类: A类: CPrintDialog.DoModal,然后在模态对话框里选打印机.打印配置: B类:GetPrinterDeviceDefault ...
- js在HTML中的三种写法
1.内联样式 内联样式分为两种,一是直接写入元素的标签内部 <html> <title>js样式内联写法</title> <meta http-equiv=& ...
- Leetcode 220.存在重复元素III
存在重复元素III 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. ...