zoukankan      html  css  js  c++  java
  • P3250 [HNOI2016]网络

    链接

    一个很暴力的做法是直接树剖,对除路径上 (log n) 个区间之外的加入决策,很明显要修改的区间也有 (log n) 个,因为要支持删除,所以每个节点要加一个延迟删除的堆来维护,时间复杂度 (O(n log^3 n))

    发现决策会维持一段区间,可以用线段树分治,于是节点上可以不用堆而只用一个单调栈维护,复杂度 (O(n log^3 n))

    考虑二分一个值 (val) ,将 (v geq val) 的路径上的节点加一,如果询问节点值等于加入路径的值,则 (ans < val),否则 (ans geq val)
    于是差分 (+) 整体二分,树状数组维护即可,复杂度 (O(n log^2 n))

    #include<bits/stdc++.h>
    #define IL inline
    #define LL long long
    using namespace std;
    const int N=2e5+3;
    struct kk{
      int to,nxt;
    }e[N<<1];
    struct hh{
      int op,id,x,y,lca,v;
    }q[N],ql[N],qr[N];
    int n,m,num,cnt,b[N],fir[N],ans[N];
    int siz[N],dep[N],dfn[N],top[N],son[N],fa[N];
    IL int in(){
      char c;int f=1;
      while((c=getchar())<'0'||c>'9')
        if(c='-') f=-1;
      int x=c-'0';
      while((c=getchar())>='0'&&c<='9')
        x=x*10+c-'0';
      return x*f;
    }
    IL void add(int x,int y){e[++num]=(kk){y,fir[x]},fir[x]=num;}
    void dfs1(int u,int f){
      siz[u]=1,dep[u]=dep[f]+1,fa[u]=f;
      for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
        if(v^f){
    		  dfs1(v,u),siz[u]+=siz[v];
    		  if(siz[son[u]]<siz[v]) son[u]=v;
    		}
    }
    void dfs2(int u,int t){
      dfn[u]=++num,top[u]=t;
      if(son[u]) dfs2(son[u],t);
      for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
        if(v^fa[u]&&v^son[u]) dfs2(v,v);
    }
    IL int Lca(int x,int y){
      while(top[x]^top[y]) dep[top[x]]<dep[top[y]]?y=fa[top[y]]:x=fa[top[x]];
      return dep[x]<dep[y]?x:y;
    }
    struct BIT{
      int c[N];
      IL int lb(int x){return x&-x;}
      IL void add(int y,int x){for(;y<=n;y+=lb(y)) c[y]+=x;}
      IL int ask(int y){int res=0;for(;y;y-=lb(y)) res+=c[y];return res;}
      IL void mdy(hh a,int v){
    		add(dfn[a.x],v),add(dfn[a.y],v),add(dfn[a.lca],-v);
    		if(a.lca^1) add(dfn[fa[a.lca]],-v);
    	}
    	IL int query(int x){return ask(dfn[x]+siz[x]-1)-ask(dfn[x]-1);}
    }T;
    void solve(int l,int r,int ll,int rr){
      if(ll>rr) return;
      int c=0;
      if(l==r){
    	  for(int i=ll;i<=rr;++i)
    	    if(q[i].op^2) T.mdy(q[i],q[i].op?-1:1),c+=q[i].op?-1:1;
    	    else ans[q[i].id]=(T.query(q[i].x)^c?b[l]:-1);
    	  for(int i=ll;i<=rr;++i) if(q[i].op^2) T.mdy(q[i],q[i].op?1:-1);
    	  return;
    	}
    	int mid=l+r>>1,nl=0,nr=0;
    	for(int i=ll;i<=rr;++i)
    	  if(q[i].op^2){
    		  if(q[i].v>mid) T.mdy(q[i],q[i].op?-1:1),c+=q[i].op?-1:1,qr[++nr]=q[i];
    		  else ql[++nl]=q[i];
    		}
    	  else if(T.query(q[i].x)^c) qr[++nr]=q[i];
    	  else ql[++nl]=q[i];
    	for(int i=ll;i<=rr;++i) if(q[i].op^2&&q[i].v>mid) T.mdy(q[i],q[i].op?1:-1);
    	for(int i=1;i<=nl;++i) q[ll+i-1]=ql[i];
    	for(int i=1;i<=nr;++i) q[ll+nl+i-1]=qr[i];
    	solve(l,mid,ll,ll+nl-1),solve(mid+1,r,ll+nl,rr);
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	int op,x,y,z;
    	n=in(),m=in();
    	for(int i=1;i<n;++i)
    	  x=in(),y=in(),
    	  add(x,y),add(y,x);
    	num=0,dfs1(1,0),dfs2(1,1);
    	for(int i=1;i<=m;++i){
    	  op=in();
    	  if(!op) x=in(),y=in(),q[i]=(hh){op,i,x,y,Lca(x,y),b[++cnt]=in()},ans[i]=-2;
    	  else if(op==1) x=in(),q[i]=q[x],q[i].op=1,ans[i]=-2;
    	  else q[i]=(hh){op,i,in(),0,0,0};
    	}
    	sort(b+1,b+cnt+1),cnt=unique(b+1,b+cnt+1)-b-1;
    	for(int i=1;i<=m;++i) if(q[i].op^2) q[i].v=lower_bound(b+1,b+cnt+1,q[i].v)-b;
    	solve(1,cnt,1,m);
    	for(int i=1;i<=m;++i) if(ans[i]^-2) printf("%d
    ",ans[i]);
      return 0;
    }
    
  • 相关阅读:
    可序列化serializable的作用是什么
    HelloWorld编译正常运行报noclassdeffounderror
    dtd对xml没有起到约束作用
    Ajax发送XML请求案例
    Ajax发送GET和POST请求案例
    Ajax发送简单请求案例
    初识Ajax
    数据库设计
    数据库和实例的区别
    Flask
  • 原文地址:https://www.cnblogs.com/yiqiAtiya/p/14016806.html
Copyright © 2011-2022 走看看