首页 > 其他 > 详细

[BZOJ4538]网络

时间:2016-04-20 19:49:56      阅读:382      评论:0      收藏:0      [点我收藏+]

本来想用树剖艹,然而并不会卡常数这种神奇的技能,,,于是还是乖乖写正解吧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问题

技术分享
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define fir first
  4 #define sec second
  5 #define mp make_pair
  6 #define inf 0x3f3f3f3f
  7 #define maxn 100005
  8 #define maxm 200005
  9 pair<int,int>rng[maxn];
 10 struct node{
 11     int op,id,x,ans;
 12     bool operator<(const node &t)const{ return id<t.id; }
 13 }q[maxm],tmp[maxm];
 14 int cnt,v[maxn<<1],next[maxn<<1],first[maxn];
 15 int ss,ST[maxn<<2][20],log_2[maxn<<1],vis[maxn],dep[maxn];
 16 int n,m,A[maxm],B[maxm],C[maxm],dfn,BIT[maxn],fa[maxn];
 17 int read(){
 18     int ttt=0; char ch=0;
 19     while(ch<0||ch>9)ch=getchar();
 20     while(ch>=0&&ch<=9)ttt=ttt*10+ch-0,ch=getchar();
 21     return ttt;
 22 }
 23 void add(int st,int end){
 24     v[++cnt]=end;
 25     next[cnt]=first[st];
 26     first[st]=cnt;
 27 }
 28 void dfs(int x){
 29     rng[x].fir=++dfn;
 30     ST[++ss][0]=x;
 31     if(!vis[x])vis[x]=ss;
 32     for(int e=first[x];e;e=next[e])
 33         if(v[e]!=fa[x]){
 34             fa[v[e]]=x,dep[v[e]]=dep[x]+1;
 35             dfs(v[e]);
 36             ST[++ss][0]=x;
 37         }
 38     rng[x].sec=dfn;
 39 }
 40 int Min(int x,int y){
 41     return dep[x]<dep[y]?x:y;
 42 }
 43 void build_ST(){
 44     log_2[1]=0;
 45     for(int i=2;i<=ss;i++)
 46         log_2[i]=log_2[i>>1]+1;
 47     for(int j=1;j<=log_2[ss];j++)
 48         for(int i=1;i<=ss;i++)
 49             ST[i][j]=Min(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
 50 }
 51 void update(int pos,int x){
 52     for(int i=pos;i<=n;i+=i&-i)
 53         BIT[i]+=x;
 54 }
 55 int query_ST(int x,int y){
 56     x=vis[x],y=vis[y];
 57     if(x>y)swap(x,y);
 58     int len=log_2[y-x+1];
 59     return Min(ST[x][len],ST[y-(1<<len)+1][len]);
 60 }
 61 //update操作传参biubiu
 62 void update_op(int x,int y,int op){
 63     int lca=query_ST(x,y);
 64     update(rng[x].fir,op),update(rng[y].fir,op);
 65     update(rng[lca].fir,-op);
 66     if(fa[lca])update(rng[fa[lca]].fir,-op);//
 67 }
 68 int query(int pos){
 69     int sum=0;
 70     for(int i=pos;i;i-=i&-i)sum+=BIT[i];
 71     return sum;
 72 }
 73 int query_op(int x){
 74     return query(rng[x].sec)-query(rng[x].fir-1);
 75 }
 76 void erfn(int L,int R,int l,int r){
 77     if(L>R)return;//
 78     int mid=(l+r)>>1;
 79     if(l==r){
 80         for(int i=L;i<=R;i++)
 81             if(q[i].op==2)q[i].ans=mid;
 82         return;
 83     }
 84     int qq=L-1,tt=0,num=0;
 85     for(int i=L;i<=R;i++){
 86         if(q[i].op==2){
 87             if(query_op(q[i].x)==num)q[++qq]=q[i];
 88             else tmp[++tt]=q[i];
 89         }
 90         else{
 91             int op=q[i].op?-1:1;
 92             if(C[q[i].x]<=mid)q[++qq]=q[i];
 93             else{
 94                 tmp[++tt]=q[i],num+=op;
 95                 update_op(A[q[i].x],B[q[i].x],op);
 96             }
 97         }
 98     }
 99     for(int i=1;i<=tt;i++)
100         if(tmp[i].op!=2){
101             int op=tmp[i].op?1:-1;
102             update_op(A[tmp[i].x],B[tmp[i].x],op);
103         }
104     for(int i=1;i<=tt;i++)q[qq+i]=tmp[i];
105     erfn(L,qq,l,mid);
106     erfn(qq+1,qq+tt,mid+1,r);
107 }
108 int main(){
109     n=read(),m=read();
110     int a,b;
111     for(int i=1;i<n;i++){
112         a=read(),b=read();
113         add(a,b),add(b,a);
114     }
115     dfs(1);
116     build_ST();
117     int r=0;
118     for(int i=1;i<=m;i++){
119         q[i].op=read();
120         q[i].id=i;
121         if(q[i].op==0){
122             A[i]=read(),B[i]=read(),C[i]=read();
123             q[i].x=i;
124             r=max(r,C[i]);
125         }
126         else q[i].x=read();
127     }
128     erfn(1,m,-1,r);//
129     sort(q+1,q+1+m);
130     for(int i=1;i<=m;i++)
131         if(q[i].op==2)printf("%d\n",q[i].ans);
132     return 0;
133 }
View Code

 

[BZOJ4538]网络

原文:http://www.cnblogs.com/Ngshily/p/5413933.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!