luogu3250 网络 (整体二分+树上差分+树状数组)

首先整体二分,问题变成是否存在经过一个点的满足条件的路径

那么我对于每个路径(a,b,lca),在树状数组的dfn[a]++,dfn[b]++,dfn[lca]--,dfn[fa[lca]--]

然后直接查那个点的子树和就行了

  1 #include<bits/stdc++.h>
  2 #define CLR(a,x) memset(a,x,sizeof(a))
  3 #define MP make_pair
  4 using namespace std;
  5 typedef long long ll;
  6 typedef unsigned long long ull;
  7 typedef pair<int,int> pa;
  8 const int maxn=2e5+10,maxm=4e5+10;
  9 
 10 inline ll rd(){
 11     ll x=0;char c=getchar();int neg=1;
 12     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 13     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 14     return x*neg;
 15 }
 16 
 17 int N,M,eg[maxn*2][2],egh[maxn],ect;
 18 int dfn[maxn][2],tot,fa[maxn][20],dep[maxn];
 19 int tr[maxn],ans[maxm],que[maxm];
 20 
 21 inline int lowbit(int x){return x&(-x);}
 22 inline void add(int x,int y){
 23     for(;x&&x<=N;x+=lowbit(x)) tr[x]+=y;
 24 }
 25 inline int query(int x){
 26     int re=0;for(;x;x-=lowbit(x)) re+=tr[x];return re; 
 27 }
 28 
 29 struct Node{
 30     int d,a,b,v,lca;
 31     Node(int x=0,int y=0,int z=0,int l=0,int k=0){
 32         d=x,a=y,b=z,v=l,lca=k;
 33     }
 34     inline void cover(int x){
 35         add(dfn[a][0],d*x);
 36         add(dfn[b][0],d*x);
 37         add(dfn[lca][0],-d*x);
 38         add(dfn[fa[lca][0]][0],-d*x);
 39     }
 40 }op[maxm],tmp[maxm];
 41 
 42 inline void adeg(int a,int b){
 43     eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect;
 44 }
 45 
 46 inline void dfs(int x){
 47     for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++)
 48         fa[x][i+1]=fa[fa[x][i]][i];
 49     dfn[x][0]=++tot;
 50     for(int i=egh[x];i;i=eg[i][1]){
 51         int b=eg[i][0];if(b==fa[x][0]) continue;
 52         dep[b]=dep[x]+1,fa[b][0]=x;dfs(b);
 53     }dfn[x][1]=tot;
 54 }
 55 
 56 inline int getlca(int x,int y){
 57     if(dep[x]<dep[y]) swap(x,y);
 58     for(int i=log2(dep[x]-dep[y]);i>=0&&dep[x]!=dep[y];i--){
 59         if(dep[fa[x][i]]>=dep[y])
 60             x=fa[x][i];
 61     }
 62     if(x==y) return x;
 63     for(int i=log2(dep[x]);i>=0;i--){
 64         if(fa[x][i]!=fa[y][i])
 65             x=fa[x][i],y=fa[y][i];
 66     }return fa[x][0];
 67 }
 68 
 69 inline void solve(int l,int r,int vl,int vr){
 70     if(l>r||vl>vr) return;
 71     int a=l-1,b=r+1,mid=vl+vr>>1;
 72     int cnt=0;
 73     
 74     for(int i=l;i<=r;i++){
 75         if(op[i].d){
 76             if(op[i].v>=mid) tmp[--b]=op[i],op[i].cover(1),cnt+=op[i].d;
 77             else tmp[++a]=op[i];
 78         }else{
 79             int re=query(dfn[op[i].a][1])-query(dfn[op[i].a][0]-1);
 80             if(cnt-re>=1) tmp[--b]=op[i],ans[op[i].b]=mid;
 81             else tmp[++a]=op[i];
 82         }
 83     }
 84     
 85     for(int i=l;i<=r;i++){
 86         if(op[i].d&&op[i].v>=mid) op[i].cover(-1);
 87     }
 88     
 89     for(int i=l;i<=a;i++) op[i]=tmp[i];
 90     for(int i=r;i>=b;i--) op[i]=tmp[r-i+b];
 91     solve(l,a,vl,mid-1);solve(b,r,mid+1,vr);
 92 }
 93 
 94 int main(){
 95     // freopen("network4.in","r",stdin);
 96     int i,j,k;
 97     N=rd(),M=rd();
 98     for(i=1;i<N;i++){
 99         int a=rd(),b=rd();
100         adeg(a,b);adeg(b,a);
101     }
102     dep[1]=1;dfs(1);
103     for(i=1,j=0;i<=M;i++){
104         int o=rd();
105         if(o==0){
106             int a=rd(),b=rd(),c=rd();
107             op[i]=Node(1,a,b,c,getlca(a,b));
108         }else if(o==1){
109             int t=rd();
110             op[i]=Node(-1,op[t].a,op[t].b,op[t].v,op[t].lca);
111         }else{
112             op[i]=Node(0,rd(),i,0,0);
113             que[++j]=i;
114         }
115     }
116     CLR(ans,-1);
117     solve(1,M,1,1e9);
118     for(i=1;i<=j;i++){
119         printf("%d\n",ans[que[i]]);
120     }
121     return 0;
122 }

 

posted @ 2018-12-01 19:01  Ressed  阅读(149)  评论(0编辑  收藏  举报