【HNOI2016】网络
题面
题解
考虑整体二分。
定义整体二分函数solve(l, r, ql, qr)表示操作权值在\([l, r]\)中,对\([ql, qr]\)的询问进行二分。
这样的话check就会很简单,先按照时间将所有\(\geq mid\)的边加进去,对于每个点判断是不是所有路径都经过了这个点就可以判断这个点的答案是不是\(\geq mid\)
具体如何判断的话可以用树上差分。
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))
inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
}
const int maxn(100010), maxm(200010);
struct edge { int next, to; } e[maxn << 1];
int head[maxn], e_num, n, m;
inline void add_edge(int from, int to)
{
e[++e_num] = (edge) {head[from], to};
head[from] = e_num;
}
int size[maxn], heavy[maxn], pos[maxn], fa[maxn], belong[maxn], cnt;
void dfs(int x)
{
size[x] = 1;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(to == fa[x]) continue;
fa[to] = x; dfs(to); size[x] += size[to];
if(size[heavy[x]] < size[to]) heavy[x] = to;
}
}
void dfs(int x, int chain)
{
pos[x] = ++cnt; belong[x] = chain;
if(!heavy[x]) return;
dfs(heavy[x], chain);
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to;
if(to == fa[x] || to == heavy[x]) continue;
dfs(to, to);
}
}
struct qry { int opt, from, to, dis, id, lca, y; } s[maxm], pl[maxm], pr[maxm];
int U[maxm], ucnt, ans[maxm], c[maxm];
void update(int x, int v) { while(x <= n) c[x] += v, x += x & -x; }
int query(int x) { int a = 0; while(x) a += c[x], x -= x & -x; return a; }
void Div(int l, int r, int ql, int qr)
{
if(ql > qr) return;
bool flag = 1; int cntl = 0, cntr = 0;
for(RG int i = ql; i <= qr; i++)
if(s[i].opt == 2) { flag = 0; break; }
if(flag) return;
if(l == r)
{
for(RG int i = ql; i <= qr; i++)
if(s[i].id) ans[s[i].id] = l;
return;
}
int mid = (l + r) >> 1, sum = 0;
for(RG int i = ql; i <= qr; i++)
if(s[i].opt == 2)
{
if(query(pos[s[i].from] + size[s[i].from] - 1) -
query(pos[s[i].from] - 1) == sum) pr[++cntr] = s[i];
else pl[++cntl] = s[i];
}
else if(s[i].dis <= mid)
{
int d = s[i].opt ? -1 : 1; sum += d;
update(pos[s[i].from], d); update(pos[s[i].to], d);
update(pos[s[i].lca], -d);
if(s[i].lca != 1) update(pos[fa[s[i].lca]], -d);
pl[++cntl] = s[i];
}
else pr[++cntr] = s[i];
memcpy(s + ql, pl + 1, sizeof(qry) * cntl);
memcpy(s + ql + cntl, pr + 1, sizeof(qry) * cntr);
for(RG int i = ql; i <= qr; i++)
if(s[i].opt != 2 && s[i].dis <= mid && s[i].y)
{
int d = s[i].opt ? 1 : -1;
update(pos[s[i].from], d); update(pos[s[i].to], d);
update(pos[s[i].lca], -d);
if(s[i].lca != 1) update(pos[fa[s[i].lca]], -d);
}
Div(l, mid, ql, ql + cntl - 1), Div(mid + 1, r, ql + cntl, qr);
}
int main()
{
n = read(), m = read();
for(RG int i = 1, a, b; i < n; i++)
a = read(), b = read(),
add_edge(a, b), add_edge(b, a);
dfs(1); dfs(1, 1);
for(RG int i = 1; i <= m; i++)
{
s[i].opt = read();
if(s[i].opt == 0)
{
int x = s[i].from = read(), y = s[i].to = read();
U[++ucnt] = -(s[i].dis = read()), s[i].y = 1;
while(belong[x] != belong[y])
{
if(pos[belong[x]] < pos[belong[y]]) std::swap(x, y);
x = fa[belong[x]];
}
s[i].lca = (pos[x] < pos[y] ? x : y);
}
else if(s[i].opt == 1)
{
int x = read(); s[i] = s[x]; s[i].opt = 1;
s[i].y = s[x].y = 0;
}
else s[i].from = read(), s[i].id = ++ans[0];
}
U[++ucnt] = 1; std::sort(U + 1, U + ucnt + 1);
ucnt = std::unique(U + 1, U + ucnt + 1) - U - 1;
for(RG int i = 1; i <= m; i++) if(s[i].opt != 2)
s[i].dis = std::lower_bound(U + 1, U + ucnt + 1, -s[i].dis) - U;
for(RG int i = 1; i <= ucnt; i++) U[i] = -U[i];
Div(1, ucnt, 1, m);
for(RG int i = 1; i <= ans[0]; i++) printf("%d\n", U[ans[i]]);
return 0;
}
【HNOI2016】网络的更多相关文章
- 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\)的乱搞. 先树剖,线段树套堆维护区间最大值.对于一次修改,如果是插入,就把 ...
- 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组
[BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...
- Luogu-3250 [HNOI2016]网络
Luogu-3250 [HNOI2016]网络 题面 Luogu-3250 题解 CDQ分治...这个应该算是整体二分吧 二分重要度,按照时间从小到大加入大于重要度的边 对于一个询问,如果经过这个点的 ...
- (BZOJ4538)HNOI2016 网络
HNOI2016 Day1 T2 网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互时,数 ...
- P3250 [HNOI2016]网络
LINK:网络 一棵树 每次添加一条路径 或者删除之前的一条路径 或询问除了不经过某个点之外剩下的最大值. 一个显然的思路 对于一条路径的权值我们直接把权值塞上去 标记永久化一下即可. 考虑如何求答案 ...
- BZOJ4538 : [Hnoi2016]网络
求出这棵树的dfs序,对于一条链$u-v$,假设$st[u]\leq st[v]$,那么一条链不经过点$x$当且仅当它满足下面任意一个条件: 1.$st[v]<st[x]$ 2.$st[u]&g ...
- HNOI2016 网络
题目 朴素算法 在线. 树链剖分套一个堆. 时间复杂度\(O(n (\log n)^3)\). 分治 朴素算法中,套一个堆是为了支持删除操作. 采用以下分治可以避免删除操作: 每次对时间\([l,r] ...
随机推荐
- React Native 如何做轮播图 react-native-swiper
//:仿饿了么github:https://github.com/stoneWeb/elm-react-native 欢迎各位同学加入: React-Native群:397885169 大前端群:54 ...
- 记一款bug管理系统(bugdone.cn)的开发过程(4) - 新增BugTalk功能
测试人员提出一个Bug,如果开发人员对Bug有疑义,会直接面对面讨论或者通过QQ等线上聊天工具讨论,但过后再去找讨论记录会很麻烦.因此BugDone提出一个全新的概念:将问题的讨论留在问题内.BugD ...
- Ubuntu 18.04 修改为静态IP
1.进入/etc/netplan目录 cd /etc/netplan 2.查看文件 ls 3.编辑 01-network-manager-all.yaml vim 01-network-manager ...
- jmeter之数据库相关
一.JDBC Connection Configuration 1.Variable Name Bound to Pool-Variable Name:连接池名称, JDBC Request通过此名称 ...
- Tidb数据库报错:Transaction too large
Tidb是一个支持ACID的分布式数据库,当你导入一个非常大的数据集时,这时候产生的事务相当严重,并且Tidb本身对事物的大小也是有一个严格的控制. 有事务大小的限制主要在于 TiKV 的实现用了一致 ...
- 写博的第一天 0x00
作为一个大学生,我觉得自己除了睡觉,打游戏,吃饭更应该做点有意义的事情,作为计算机专业的学生,更应该勤奋点,主动去学习.已经要大三了,我认识到这个暑假我必须学点什么了,为了更好的学习,我决定学语言的同 ...
- Python第一篇-简介和入门
简介: Python[1] (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第 ...
- ansible(一)
Ansible简介 Ansible:Ansible的核心程序Host Lnventory:记录了每一个由Ansible管理的主机信息,信息包括ssh端口,root帐号密码,ip地址等等.可以通过fil ...
- Android Studio快捷键——编辑篇
Android Studio是官方推出的Android开发IDE,本系列讲解Android Studio中常用的快捷键,本文是该系列的第一篇,讲解的内容是与编辑代码相关的快捷键. 本文所讲快捷键基于A ...
- php 基于redis计数器类
本文引自网络 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 本文将使用其incr(自增),get(获取), ...