[BZOJ4538]网络
今天打比赛,毒瘤yww把这题出到$n,m\leq 5\times10^5$,因为不会写整体二分所以来写坑爹的$O\left(n\log_2n\right)$做法
考虑按重要度建权值线段树(相同权值的请求视作不同的),每个线段树节点存这个区间内的链的交集
那么插入删除就直接搞,询问时在线段树上贪心,如果当前节点的右儿子有请求且它的链交集不覆盖询问点,那么往右儿子走,否则往左儿子走
链的交集还是链,我们要求$(a,b)$和$(c,d)$的交集,如果$lca_{a,b}$在$(c,d)$上,那么一定有交集,交集为$(\text{low}({lca_{c,a}},lca_{c,b}),\text{low}(lca_{d,a},lca_{d,b}))$(其中$\text{low}(a,b)$表示$a,b$中的较低点),反过来也是一样的
细节有点多,为了跑得更快,求lca的部分可以转成rmq然后用ST表$O(1)$查询
#include<stdio.h> #include<map> using namespace std; int h[100010],nex[200010],to[200010],fa[100010],dep[100010],fir[100010],dfn[200010],mp[200010][20],log2[200010],M; void add(int a,int b){ M++; to[M]=b; nex[M]=h[a]; h[a]=M; } void dfs(int x){ M++; dfn[M]=x; fir[x]=M; for(int i=h[x];i;i=nex[i]){ if(to[i]!=fa[x]){ dep[to[i]]=dep[x]+1; fa[to[i]]=x; dfs(to[i]); M++; dfn[M]=x; } } } int querymin(int l,int r){ int k=log2[r-l+1]; if(dep[dfn[mp[l][k]]]<dep[dfn[mp[r-(1<<k)+1][k]]]) return mp[l][k]; else return mp[r-(1<<k)+1][k]; } int lca(int x,int y){ if(fir[x]>fir[y])swap(x,y); return dfn[querymin(fir[x],fir[y])]; } struct ask{ int op,x,y,v,id; }q[200010]; bool operator<(ask a,ask b){ if(a.v==b.v)return a.id<b.id; return a.v<b.v; } map<ask,int>pos; map<ask,int>::iterator it; int s[800010],lp[800010],rp[800010],rv[200010]; int dis(int x,int y){ return dep[x]+dep[y]-2*dep[lca(x,y)]; } bool inc(int x,int y,int u){ return dis(x,u)+dis(u,y)==dis(x,y); } void pushup(int x){ if(s[x<<1]==0||s[x<<1|1]==0){ lp[x]=lp[x<<1]|lp[x<<1|1]; rp[x]=rp[x<<1]|rp[x<<1|1]; return; } if(lp[x<<1]==0||lp[x<<1|1]==0){ lp[x]=rp[x]=0; return; } int a,b,c,d,e,f,h,i; a=lp[x<<1]; b=rp[x<<1]; c=lca(a,b); d=lp[x<<1|1]; e=rp[x<<1|1]; f=lca(d,e); if(inc(a,b,f)){ h=lca(d,a); i=lca(d,b); lp[x]=dep[h]>dep[i]?h:i; h=lca(e,a); i=lca(e,b); rp[x]=dep[h]>dep[i]?h:i; return; } if(inc(d,e,c)){ h=lca(a,d); i=lca(a,e); lp[x]=dep[h]>dep[i]?h:i; h=lca(b,d); i=lca(b,e); rp[x]=dep[h]>dep[i]?h:i; return; } lp[x]=rp[x]=0; } void insert(int p,int L,int R,int l,int r,int x){ s[x]++; if(l==r){ lp[x]=L; rp[x]=R; return; } int mid=(l+r)>>1; if(p<=mid) insert(p,L,R,l,mid,x<<1); else insert(p,L,R,mid+1,r,x<<1|1); pushup(x); } void erase(int p,int l,int r,int x){ s[x]--; if(l==r){ lp[x]=rp[x]=0; return; } int mid=(l+r)>>1; if(p<=mid) erase(p,l,mid,x<<1); else erase(p,mid+1,r,x<<1|1); pushup(x); } int query(int u,int l,int r,int x){ if(s[x]==0)return-1; if(l==r)return inc(lp[x],rp[x],u)?-1:rv[l]; int mid=(l+r)>>1; if(s[x<<1|1]!=0&&(lp[x<<1|1]==0||!inc(lp[x<<1|1],rp[x<<1|1],u))) return query(u,mid+1,r,x<<1|1); else return query(u,l,mid,x<<1); } int main(){ int n,m,i,j,x,y; scanf("%d%d",&n,&m); for(i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } M=0; dfs(1); for(i=2;i<=M;i++)log2[i]=log2[i>>1]+1; for(i=1;i<=M;i++)mp[i][0]=i; for(j=1;j<20;j++){ for(i=1;i<=M;i++){ if(i+(1<<j)-1<=M){ if(dep[dfn[mp[i][j-1]]]<dep[dfn[mp[i+(1<<(j-1))][j-1]]]) mp[i][j]=mp[i][j-1]; else mp[i][j]=mp[i+(1<<(j-1))][j-1]; } } } for(i=1;i<=m;i++){ scanf("%d%d",&q[i].op,&q[i].x); if(q[i].op==0){ scanf("%d%d",&q[i].y,&q[i].v); q[i].id=i; pos[q[i]]=1; } } M=1; for(it=pos.begin();it!=pos.end();it++,M++){ it->second=M; rv[M]=(it->first).v; } M--; for(i=1;i<=m;i++){ if(q[i].op==0)insert(pos[q[i]],q[i].x,q[i].y,1,M,1); if(q[i].op==1)erase(pos[q[q[i].x]],1,M,1); if(q[i].op==2)printf("%d\n",query(q[i].x,1,M,1)); } }
[BZOJ4538]网络的更多相关文章
- 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组
[BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...
- (BZOJ4538)HNOI2016 网络
HNOI2016 Day1 T2 网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互时,数 ...
- BZOJ4538 HNOI2016网络(树链剖分+线段树+堆/整体二分+树上差分)
某两个点间的请求只对不在这条路径上的询问有影响.那么容易想到每次修改除该路径上的所有点的答案.对每个点建个两个堆,其中一个用来删除,线段树维护即可.由于一条路径在树剖后的dfs序中是log个区间,所以 ...
- BZOJ4538 : [Hnoi2016]网络
求出这棵树的dfs序,对于一条链$u-v$,假设$st[u]\leq st[v]$,那么一条链不经过点$x$当且仅当它满足下面任意一个条件: 1.$st[v]<st[x]$ 2.$st[u]&g ...
- 【BZOJ4538】【HNOI2016】网络(树链剖分,线段树,堆)
题目链接,我是真的懒得调题目的格式... 题解 树链剖分搞一下LCA 把线段树弄出来 这只是形式上的线段树 本质上是维护一段区间的一个堆 每次把堆插入节点, 询问的时候查询线段树上的堆的最大值就行了 ...
- 2019.01.13 bzoj4538: [Hnoi2016]网络(树链剖分)
传送门 树链剖分一眼题. 题意简述: 给定一棵树,有三种操作: 加入一条路径 删除一条已加入的路径 询问不过一个点x的路径的最大值. 思路: 直接树链剖分维护答案. 因为询问的事不过点xxx的最大值, ...
- BZOJ4538:[HNOI2016]网络(树链剖分,堆)
Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做 一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有 ...
- 【bzoj4538】[Hnoi2016]网络
我们考虑树剖,线段树上维护一个堆,保存不经过该段区间的路径的权值. 对于一条路径我们将对于线段树中的区间提取出来,在对于线段树中进行修改.也就是在堆中插入或删除. 对于一次询问,只要找到包含该点的线段 ...
- 并不对劲的bzoj4538:loj2049:p3250:[HNOI2016]网络
题意 有一棵\(n\)(\(n\leq 10^5\))个点的树,\(m\)(\(m\leq 2\times 10^5\))个操作.操作有三种:1.给出\(u,v,k\),表示加入一条从\(u\)到\( ...
随机推荐
- 原生toolbar基本使用教程
1.先写布局文件 <android.support.v7.widget.Toolbar android:id="@+id/toolbar" app:title=" ...
- Ecplise添加XML自动提示
这里以struts.xml为例 第一步: 首先找到 struts2的核心jar包,我这里是struts2-core-2.3.20.jar用压缩工具打开或者解压下来
- js操作div的显隐
<!DOCTYPE html><html> <head> <title> new document </title> <meta ht ...
- GoogleMap在js中的应用
<html> <head> <meta name="viewport" content="initial-scale=1.0, user-s ...
- 100个Swift必备Tips(第二版)
100个Swift必备Tips(第二版) 新年第一天,给大家一本电子书,希望新的一年里,步步高升. GitHub
- mysql 基本操作练习
), sex ), age )); , '北京'); , '上海'); , '广州'); , '北京'); , '北京'); , '上海'); , '北京'); #(). 写出sql语句,查询所有年龄 ...
- jquery——通过name属性查找元素
Js代码 : $("div[id]") 选择所有含有id属性的div元素 $("input[name='newsletter']") 选择所有的name属性 ...
- 基于x64的处理器意思
基于x64的处理器意思是CPU的架构是X64的,也是64位的CPU. 基本简介: "x86-64",有时会简称为"x64",是64位微处理器架构及其相应指令集的 ...
- 链接加载文件gcc __attribute__ section
在阅读源代码的过程中,发现一个头文件有引用: /** The address of the first device table entry. */ extern device_t devices[] ...
- 【C++】指针和new相关
看黄邦勇帅的笔记. 指针和new之前觉得已经掌握的很好了,可是看了资料还是get到了新知识.记录一下. 1.指针只支持 4 种算术运算符:++,――,+,-.指针只能与整数加减.指针运算的原则是:每当 ...