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 ...
随机推荐
- ZBarReaderView屏幕旋转问题
转载:http://42.96.197.72/ios-zbarreaderview-interface-orientation/ 在iPad应用中,如果没有特殊情况,需要让应用支持所有屏幕方向.在iP ...
- hdu1066(经典题)
求N个数阶乘末尾除0后的数值. 主要的难点在于要把这个N个数所含的2和5的队数去掉. 网上方法很多很好. 不多说 Last non-zero Digit in N! Time Limit: 2000/ ...
- 妈妈再也不用担心我使用git了
妈妈再也不用担心我使用git了 Dec 29, 2014 git git由于其灵活,速度快,离线工作等特点而倍受青睐,下面一步步来总结下git的基本命令和常用操作. 安装msysgit 下载地址:ms ...
- centos6.5上搭建gitlab服务器(亲测可用哦)
最近的版本控制中,git可谓是脱缰的野马,一发不可收拾.当然git的设计模式也是愈发的成熟,让人刮目相看,完美解决了svn上的不足之处.在目前分布式横行的天下,git可谓是占得了一席之地. 废话少说, ...
- iOS中nil 、NULL、 Nil 、NSNull
nil,定义一个空的实例,指向OC中对象的空指针. 示例代码: NSString *someString = nil; NSURL *someURL = nil; id someObject = ni ...
- Checksum 磁盘扇区故障检测
w https://en.wikipedia.org/wiki/Checksum https://zh.wikipedia.org/wiki/校验和 A checksum is a small-siz ...
- selectedIndex返回被选中的option的index.
/ <label for="city">城市</label> <select id="city" name="schoo ...
- lua53编译
#下载lua包lua-5.3.5 #vs2017新建个空工程,删除lua.c,luac,c,设置配置类型 动态库.dll #编译完成
- json的相关操作
最近对json的操作不是很理解 定义: JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式. 它基于 ECMAScript (w3c制定的j ...
- eslasticsearch操作集锦
索引-index:一个索引就是一个拥有几分相似特征的文档的集合.比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引.一个索引由一个名字来标识(必须全部是小写字母的),并且 ...