把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P3250 [HNOI2016]网络

题面传送门
一眼线段树分治然而想想都会T
考虑什么更优的算法。
我们用线段树维护权值大于\(w\)的树上路径交,然后线段树上二分,看看树上路径交是否包含这个点即可。
时间复杂度\(O(nlogn)\),需要使用\(O(1)\)LCA
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define lb long db
#define N 200000
#define mod 1000000007
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Pc(x) putchar(x) 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,x[N+5],y[N+5],z[N+5],op[N+5],d[N+5],lg[N+5],dfn[N+5<<1],dh,bg[N+5],st[N+5<<1][20],A[10],nows[N+5],Nh,W[N+5],Lx,Ly;
struct yyy{int to,z;};I bool cmp1(int x,int y){return d[x]>d[y];}I bool cmp2(int x,int y){return z[x]<z[y];}struct path{int x,y;I int H(){return ~x;}}Cl=(path){-1,-1},Bl;
struct ljb{int head,h[N+5];yyy f[N+5<<1];I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}}s;
I void Make(int x,int last){d[x]=d[last]+1;dfn[bg[x]=++dh]=x;yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(Make(tmp.to,x),dfn[++dh]=x);}
I int L(int x,int y){x=bg[x];y=bg[y];x>y&&(swap(x,y),0);int p=lg[y-x+1];return d[st[x][p]]<d[st[y-(1<<p)+1][p]]?st[x][p]:st[y-(1<<p)+1][p];} 
I path merge(path x,path y){
	if(x.x==-1||y.y==-1) return Cl;if(!x.x||!y.x)return (path){x.x+y.x,x.y+y.y};
    A[0]=L(x.x,y.x);A[1]=L(x.x,y.y);A[2]=L(x.y,y.x);A[3]=L(x.y,y.y);sort(A,A+4,cmp1);return A[0]^A[1]?(path){A[0],A[1]}:((d[A[0]]>=d[L(x.x,x.y)]&&d[A[0]]>=d[L(y.x,y.y)])?(path){A[0],A[0]}:Cl);
}
struct Tree{
	#define ls now<<1
	#define rs now<<1|1
	path F[N+5<<2];I void build(int l=0,int r=Nh,int now=1){if(l==r) return;int m=l+r>>1;build(l,m,ls);build(m+1,r,rs);}
	I void Get(int x,path z,int l=0,int r=Nh,int now=1){if(l==r) return (void)(F[now]=z);int m=l+r>>1;x<=m?Get(x,z,l,m,ls):Get(x,z,m+1,r,rs);F[now]=merge(F[ls],F[rs]);}
	I int Query(int x,int l=0,int r=Nh,int now=1){path S=(path){x,x};int m;while(l^r) m=l+r>>1,/*printf("%d %d %d %d\n",l,r,F[rs].x,F[rs].y),*/merge(S,F[rs]).H()?(S=merge(S,F[rs]),now=ls,r=m):(now=rs,l=m+1);return l;}
}T;
int main(){
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
	re int i,j;scanf("%d%d",&n,&m);for(i=2;i<=n;i++)scanf("%d%d",&x[0],&y[0]),s.add(x[0],y[0]),s.add(y[0],x[0]);Make(1,0);for(i=2;i<=dh;i++) lg[i]=lg[i/2]+1;
	for(i=dh;i;i--)for(st[i][0]=dfn[i],j=1;i+(1<<j)-1<=dh;j++) st[i][j]=(d[st[i][j-1]]<d[st[i+(1<<j-1)][j-1]]?st[i][j-1]:st[i+(1<<j-1)][j-1]);
	for(i=1;i<=m;i++)scanf("%d",&op[i]),!op[i]?(scanf("%d%d%d",&x[i],&y[i],&z[i]),nows[++Nh]=i):(scanf("%d",&x[i]));sort(nows+1,nows+Nh+1,cmp2);for(i=1;i<=Nh;i++)W[i]=i,swap(W[i],z[nows[i]]);
	T.build();W[0]=-1;for(i=1;i<=m;i++)!op[i]?(T.Get(z[i],(path){x[i],y[i]}),0):(op[i]^2?(T.Get(z[x[i]],Bl),0):printf("%d\n",W[T.Query(x[i])]));
}
posted @ 2021-08-18 20:03  275307894a  阅读(36)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end