Luogu-3250 [HNOI2016]网络
Luogu-3250 [HNOI2016]网络
题面
题解
CDQ分治...这个应该算是整体二分吧
二分重要度,按照时间从小到大加入大于重要度的边
对于一个询问,如果经过这个点的边数不等于加入的边数,那就说明有比重要度大而且不经过这个点的边,然后分成两部分继续做
看Candy?大佬的博客学会了一种加边方法:记录dfn序,对于一条边\(u\),\(v\)。让端点的\(cnt\)++,\(lca\)和\(fa[lca]\)的--,找经过一个点边数只需要查询他的子树大小就好啦
代码
#include<map>
#include<queue>
#include<cmath>
#include<ctime>
#include<stack>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char gc(){
//static char buf[100000],*p1,*p2;
//return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
return getchar();
}
inline int read(){
int ans=0,fh=1;
char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') fh=-1; ch=gc();}
while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=gc();
return ans*fh;
}
const int maxn=2e5+100,maxm=maxn<<1;
struct node{
int a,b,v;
}c[maxn];
int n,m,head[maxn],nex[maxm],v[maxm],num=1;
int tre[maxn],cr[maxn],cl;
int fa[maxn],top[maxn],siz[maxn],dep[maxn],son[maxn],dfn[maxn],tim;
int tmp1[maxn],tmp2[maxn],p[maxn],ans[maxn],mx,qtot;
void revise(int x,int z){
for(int i=x;i<maxn;i+=i&(-i))
if(cr[i]==cl) tre[i]+=z;
else cr[i]=cl,tre[i]=z;
}
int query(int x,int Ans=0){
for(int i=x;i;i-=i&(-i))
if(cr[i]==cl) Ans+=tre[i];
return Ans;
}
void add(int x,int y){
v[++num]=y;
nex[num]=head[x];
head[x]=num;
v[++num]=x;
nex[num]=head[y];
head[y]=num;
}
void dfs1(int x,int f,int dp){
fa[x]=f,dep[x]=dp,siz[x]=1;
for(int i=head[x];i;i=nex[i]){
int y=v[i];
if(y==f) continue;
dfs1(y,x,dp+1);
if(siz[y]>siz[son[x]])
son[x]=y;
siz[x]+=siz[y];
}
}
void dfs2(int x,int tp){
top[x]=tp,dfn[x]=++tim;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i;i=nex[i])
if(v[i]!=fa[x]&&v[i]!=son[x])
dfs2(v[i],v[i]);
}
int Lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
void work(int x,int y,int z){
int lca=Lca(x,y);
revise(dfn[x],z),revise(dfn[y],z);
revise(dfn[lca],-z);if(lca!=1) revise(dfn[fa[lca]],-z);
}
int check(int x){
int l=dfn[x],r=dfn[x]+siz[x]-1;
return query(r)-query(l-1);
}
void cdq(int l,int r,int L,int R){
if(L>R) return;
if(l==r){
int ltot=0;cl++;
for(int i=L;i<=R;i++){
int x=p[i],z=c[x].v>0?1:-1;
if(~c[x].b) work(c[x].a,c[x].b,z),ltot+=z;
else if(check(c[x].a)!=ltot) ans[c[x].v]=l;
}
return;
}
int mid=l+r>>1;
int lc=0,rc=0,cnt=L-1,ltot=0;cl++;
for(int i=L;i<=R;i++){
int x=p[i],z=c[x].v>0?1:-1;
if(~c[x].b){
if(abs(c[x].v)>mid)
work(c[x].a,c[x].b,z),tmp2[++rc]=x,ltot+=z;
else tmp1[++lc]=x;
}
else{
int pp=check(c[x].a);
if(pp!=ltot) tmp2[++rc]=x;
else tmp1[++lc]=x;
}
}
for(int i=1;i<=lc;i++) p[++cnt]=tmp1[i];
for(int i=1;i<=rc;i++) p[++cnt]=tmp2[i];
cdq(l,mid,L,L+lc-1),cdq(mid+1,r,L+lc,R);
}
int main(){
// freopen("3250.in","r",stdin);
n=read(),m=read();
int x,y,ms,z;
for(int i=1;i<n;i++)
x=read(),y=read(),add(x,y);
dfs1(1,1,1);
dfs2(1,1);
for(int i=1;i<=m;i++){
ms=read(),p[i]=i;
if(!ms){
x=read(),y=read(),z=read();
c[i]=(node){x,y,z},mx=max(mx,z);
}
else{
x=read();
if(ms==1) c[i]=c[x],c[i].v*=-1;
else c[i].a=x,c[i].b=-1,c[i].v=++qtot;
}
}
memset(ans,-1,sizeof(ans));
cdq(1,mx,1,m);
for(int i=1;i<=qtot;i++)
printf("%d\n",ans[i]);
return 0;
}
Luogu-3250 [HNOI2016]网络的更多相关文章
- luogu P3250 [HNOI2016]网络
传送门 考虑只有一个询问,怎么使用暴力枚举最快的得到答案.因为要求最大的,所以可以把链按权值从大往小排序,然后往后扫,找到一个没有交的就是答案,直接退出 一堆询问,可以考虑整体二分,先二分一个值\(m ...
- 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 2604] ZJOI2010 网络扩容
[Luogu 2604] ZJOI2010 网络扩容 第一问直接最大流. 第二问,添加一遍带费用的边,边权 INF,超级源点连源点一条容量为 \(k\) 的边来限流,跑费用流. 大约是第一次用 nam ...
- 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组
[BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...
- (BZOJ4538)HNOI2016 网络
HNOI2016 Day1 T2 网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互时,数 ...
- BZOJ 1834 Luogu P2604 [ZJOI2010]网络扩容 (最小费用最大流)
题目连接: (luogu) https://www.luogu.org/problemnew/show/P2604 (bzoj) https://www.lydsy.com/JudgeOnline/p ...
随机推荐
- jquery动态生成html代码绑定事件
今天工作中需要在页面动态生成html代码,但发现新生成的代码的click事件失效了(非动态生成的代码已经绑定了click事件),于是在网上找了很多解决办法,很多都比较复杂,且使用的jquery都比较老 ...
- 【BZOJ4145】[AMPPZ2014]The Prices 状压DP
[BZOJ4145][AMPPZ2014]The Prices Description 你要购买m种物品各一件,一共有n家商店,你到第i家商店的路费为d[i],在第i家商店购买第j种物品的费用为c[i ...
- 170210、JAVA中List、Map、Set的区别与选用
先了解下类层次关系: Collection ├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap └WeakHas ...
- java.lang.IllegalStateException: Queue full
其实异常说的很清楚 队列满了! ArrayBlockingQueue FIFO 的队列: ArrayBlockingQueue内部是通过一个Object数组和一个ReentrantLock实现的.同时 ...
- 如何cancel掉慢查询
百度Elasticsearch-产品描述-介绍-百度云 https://cloud.baidu.com/doc/BES/FAQ.html#.E5.A6.82.E4.BD.95cancel.E6.8E. ...
- 关于websocket
一句话总结: websocket可以说是基于HTTP但有有所进化的一个介于应用层和传输层的接口抽象,不是协议. 1 需要基于HTTP进行3次握手,4次挥手(在握手期间建立websocket连接,不再通 ...
- linux虚拟机连不上网络
1.修改文件ifcfg-ens33 # 切换目录 [root@localhost ~]# cd /etc/sysconfig/network-scripts/ # 将ONBOOT修改为yes [roo ...
- 006-HotSpot JVM收集器
一.概述 1.1.图解 上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器.如果两个收集器之间存在连线,就说明它们可以搭配使用. JVM给出了3类选择:串行收集器.并行收集器.并发收集 ...
- Android图片加载框架Picasso最全使用教程2
前言 前面我们已经介绍了Picasso的基本用法及如何将一张图片加载到ImageView中,下面我们就利用Picasso在ListView中加载图片;Let’s Go! 一个ListView的简单应用 ...
- eslasticsearch操作集锦
索引-index:一个索引就是一个拥有几分相似特征的文档的集合.比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引.一个索引由一个名字来标识(必须全部是小写字母的),并且 ...