[BZOJ4538]网络
2016-04-20 19:03
441 查看
本来想用树剖艹,然而并不会卡常数这种神奇的技能,,,于是还是乖乖写正解吧QAQ
我们可以把一个询问转化为二分判定性问题
二分答案$K$,若所有权值大于$K$的路径都经过询问点$x$,则答案比$K$小,否则答案比$K$大
对于多组询问,外层再套一个整体二分就行了
至于判断有几条路径经过点$x$,对于一条路径$(u,v)$我们把$u$和$v$置为$1$,$lca(u,v)$和$lca(u,v)$的父亲置为$-1$,这样经过一个节点$x$的路径条数就是以其为根的子树的标记和,,,
由于子树区间求和有关,于是可以用dfs序维护
然后可以$O(1)$求lca,即通过欧拉回路把lca转化为rmq问题
View Code
我们可以把一个询问转化为二分判定性问题
二分答案$K$,若所有权值大于$K$的路径都经过询问点$x$,则答案比$K$小,否则答案比$K$大
对于多组询问,外层再套一个整体二分就行了
至于判断有几条路径经过点$x$,对于一条路径$(u,v)$我们把$u$和$v$置为$1$,$lca(u,v)$和$lca(u,v)$的父亲置为$-1$,这样经过一个节点$x$的路径条数就是以其为根的子树的标记和,,,
由于子树区间求和有关,于是可以用dfs序维护
然后可以$O(1)$求lca,即通过欧拉回路把lca转化为rmq问题
#include<bits/stdc++.h> using namespace std; #define fir first #define sec second #define mp make_pair #define inf 0x3f3f3f3f #define maxn 100005 #define maxm 200005 pair<int,int>rng[maxn]; struct node{ int op,id,x,ans; bool operator<(const node &t)const{ return id<t.id; } }q[maxm],tmp[maxm]; int cnt,v[maxn<<1],next[maxn<<1],first[maxn]; int ss,ST[maxn<<2][20],log_2[maxn<<1],vis[maxn],dep[maxn]; int n,m,A[maxm],B[maxm],C[maxm],dfn,BIT[maxn],fa[maxn]; int read(){ int ttt=0; char ch=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9')ttt=ttt*10+ch-'0',ch=getchar(); return ttt; } void add(int st,int end){ v[++cnt]=end; next[cnt]=first[st]; first[st]=cnt; } void dfs(int x){ rng[x].fir=++dfn; ST[++ss][0]=x; if(!vis[x])vis[x]=ss; for(int e=first[x];e;e=next[e]) if(v[e]!=fa[x]){ fa[v[e]]=x,dep[v[e]]=dep[x]+1; dfs(v[e]); ST[++ss][0]=x; } rng[x].sec=dfn; } int Min(int x,int y){ return dep[x]<dep[y]?x:y; } void build_ST(){ log_2[1]=0; for(int i=2;i<=ss;i++) log_2[i]=log_2[i>>1]+1; for(int j=1;j<=log_2[ss];j++) for(int i=1;i<=ss;i++) ST[i][j]=Min(ST[i][j-1],ST[i+(1<<(j-1))][j-1]); } void update(int pos,int x){ for(int i=pos;i<=n;i+=i&-i) BIT[i]+=x; } int query_ST(int x,int y){ x=vis[x],y=vis[y]; if(x>y)swap(x,y); int len=log_2[y-x+1]; return Min(ST[x][len],ST[y-(1<<len)+1][len]); } //update操作传参biubiu void update_op(int x,int y,int op){ int lca=query_ST(x,y); update(rng[x].fir,op),update(rng[y].fir,op); update(rng[lca].fir,-op); if(fa[lca])update(rng[fa[lca]].fir,-op);// } int query(int pos){ int sum=0; for(int i=pos;i;i-=i&-i)sum+=BIT[i]; return sum; } int query_op(int x){ return query(rng[x].sec)-query(rng[x].fir-1); } void erfn(int L,int R,int l,int r){ if(L>R)return;// int mid=(l+r)>>1; if(l==r){ for(int i=L;i<=R;i++) if(q[i].op==2)q[i].ans=mid; return; } int qq=L-1,tt=0,num=0; for(int i=L;i<=R;i++){ if(q[i].op==2){ if(query_op(q[i].x)==num)q[++qq]=q[i]; else tmp[++tt]=q[i]; } else{ int op=q[i].op?-1:1; if(C[q[i].x]<=mid)q[++qq]=q[i]; else{ tmp[++tt]=q[i],num+=op; update_op(A[q[i].x],B[q[i].x],op); } } } for(int i=1;i<=tt;i++) if(tmp[i].op!=2){ int op=tmp[i].op?1:-1; update_op(A[tmp[i].x],B[tmp[i].x],op); } for(int i=1;i<=tt;i++)q[qq+i]=tmp[i]; erfn(L,qq,l,mid); erfn(qq+1,qq+tt,mid+1,r); } int main(){ n=read(),m=read(); int a,b; for(int i=1;i<n;i++){ a=read(),b=read(); add(a,b),add(b,a); } dfs(1); build_ST(); int r=0; for(int i=1;i<=m;i++){ q[i].op=read(); q[i].id=i; if(q[i].op==0){ A[i]=read(),B[i]=read(),C[i]=read(); q[i].x=i; r=max(r,C[i]); } else q[i].x=read(); } erfn(1,m,-1,r);// sort(q+1,q+1+m); for(int i=1;i<=m;i++) if(q[i].op==2)printf("%d\n",q[i].ans); return 0; }
View Code
相关文章推荐
- linux 网络编程基础(三)selsct函数应用
- Cocos2d-x3.1TestCpp之NewRenderTest Demo分析
- http、TCP/IP协议与socket之间的区别
- 网络数据请求
- 理解HTTP幂等性
- linux网络编程基础(二)
- HTTP协议详解
- Retrofit的简单封装--更方便的配置okhttp
- java获取http请求的Header和Body
- Eclipse开发web项目中关于HttpServletRequest包的问题
- Android之打开系统的网络设置
- 纽约的区块链技术能源网络改革
- iOS9+ 中http请求问题
- 请问如何用nodejs通过post发送multipart/form-data类型的http请求?
- Spring HTTP Invoker使用介绍
- HTTP中Get与Post的区别(附结合C++使用HTTP请求阅读笔记)
- HttpServletResponse对象介绍
- .net 已知图片的网络路径,通过浏览器下载图片
- TCP长连接和短连接 - http长轮询和短轮询
- Ruby使用eventmachine为HTTP服务器添加文件下载功能