本来想用树剖艹,然而并不会卡常数这种神奇的技能,,,于是还是乖乖写正解吧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 }
时间: 2024-11-02 16:09:51