<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【做題記錄】2025刷題計劃--樹上問題

      A. Minimum spanning tree for each edge

      先建出最小生成樹,對于樹邊答案就是最小生成樹,對于非樹邊就從兩個端點的路徑上刪掉權值最大的即可。
      證明:在這個環中,首先強制選了這條邊,然后按照從小到大的順序選邊,則一定不會選到刪掉的那條邊。

      Code
      #include<bits/stdc++.h>
      #define int long long
      #define il inline
      #define pb push_back
      #define pii pair<int,int>
      #define mp make_pair
      #define fir first
      #define sec second
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=2e5+5;
      int n,m,fa[maxn],sz[maxn],dep[maxn];
      int anc[maxn][22],mxv[maxn][22],ans[maxn];
      bool vis[maxn];
      struct edge{
      	int u,v,w,id;
      	il bool operator<(const edge &x)const{
      		return w<x.w;
      	}
      }a[maxn];
      vector<pii> e[maxn];
      il int find(int x){
      	return x!=fa[x]?fa[x]=find(fa[x]):x;
      }
      il void merge(int u,int v){
      	u=find(u),v=find(v);
      	if(u==v){
      		return ;
      	}
      	if(sz[u]>sz[v]){
      		sz[u]+=sz[v],fa[v]=u;
      	}
      	else{
      		sz[v]+=sz[u],fa[u]=v;
      	}
      }
      il void dfs(int u){
      //	cout<<u<<" "<<anc[u][0]<<"\n";
      	for(int i=1;i<=20;i++){
      		anc[u][i]=anc[anc[u][i-1]][i-1];
      		mxv[u][i]=max(mxv[u][i-1],mxv[anc[u][i-1]][i-1]);
      	}
      	for(pii i:e[u]){
      		int v=i.fir,w=i.sec;
      		if(v==anc[u][0]){
      			continue;
      		}
      		anc[v][0]=u,mxv[v][0]=w;
      		dep[v]=dep[u]+1;
      		dfs(v);
      	}
      }
      il int query(int u,int v){
      //	cout<<u<<" "<<v<<"\n";
      	if(dep[u]<dep[v]){
      		swap(u,v);
      	}
      	int ddep=dep[u]-dep[v],tmp=0,res=0;
      	while(ddep){
      		if(ddep&1){
      			res=max(res,mxv[u][tmp]);
      			u=anc[u][tmp];
      		}
      		ddep>>=1,tmp++;
      	}
      //	cout<<u<<" "<<v<<"\n";
      	if(u==v){ 
      //		puts("666");
      		return res;
      	}
      	for(int i=20;~i;i--){
      		if(anc[u][i]!=anc[v][i]){
      			res=max({res,mxv[u][i],mxv[v][i]});
      			u=anc[u][i],v=anc[v][i];
      		}
      	}
      	return max({res,mxv[u][0],mxv[v][0]});
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      signed main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=1;i<=m;i++){
      		cin>>a[i].u>>a[i].v>>a[i].w;
      		a[i].id=i;
      	}
      	sort(a+1,a+m+1);
      	for(int i=1;i<=n;i++){
      		fa[i]=i,sz[i]=1;
      	}
      	int res=0;
      	for(int i=1,u,v,w;i<=m;i++){
      		u=a[i].u,v=a[i].v,w=a[i].w;
      		if(find(u)!=find(v)){
      			merge(u,v);
      			vis[i]=1,res+=w;
      			e[u].pb(mp(v,w));
      			e[v].pb(mp(u,w));
      		}
      	}
      //	for(int i=1;i<=m;i++){
      //		if(vis[i]){
      //			cout<<a[i].id<<" ";
      //		}
      //	}
      //	puts("");
      	dfs(1);
      //	for(int u=1;u<=n;u++){
      //		for(int i=0;i<=3;i++){
      //			cout<<mxv[u][i]<<" ";
      //		}
      //		puts("");
      //	}
      	for(int i=1;i<=m;i++){
      		if(vis[i]){
      			ans[a[i].id]=res;
      		}
      		else{
      //			cout<<a[i].id<<" "<<query(a[i].u,a[i].v)<<"\n";
      			ans[a[i].id]=res-query(a[i].u,a[i].v)+a[i].w;
      		}
      	}
      	for(int i=1;i<=m;i++){
      		cout<<ans[i]<<"\n";
      	}
      	return 0;
      }
      }
      signed main(){return asbt::main();}
      

      B. Information Reform

      \(f_{u,i}\) 表示 \(u\) 接受 \(i\) 的信號,\(u\) 的子樹內的答案。那么可以枚舉 \(u\) 的兒子 \(v\) 接受信號的節點來轉移。注意當 \(v\) 也枚舉到 \(i\) 時要減去重復的 \(k\)
      考慮構造方案,設 \(ans_u\) 表示答案。首先可以求出 \(ans_1\)。對于 \(u\) 的每個兒子 \(v\),計算 \(u\) 是怎么從 \(v\) 轉移來的即可。仍然注意當 \(v\) 枚舉到 \(ans_u\) 時要減去重復的 \(k\)
      用 Floyd 計算兩兩之間的距離,時間復雜度 \(O(n^3)\)

      Code
      #include<bits/stdc++.h>
      #define int long long
      #define il inline
      #define pb push_back
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=205,inf=0x3f3f3f3f3f3f3f3f;
      int n,m,a[maxn],ans[maxn];
      int dis[maxn][maxn];
      int f[maxn][maxn];
      vector<int> e[maxn];
      il void dfs1(int u,int fa){
      	for(int i=1;i<=n;i++){
      		f[u][i]=a[dis[u][i]]+m;
      	}
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		dfs1(v,u);
      		for(int i=1,tmp;i<=n;i++){
      			tmp=f[u][i];
      			f[u][i]+=f[v][i]-m;
      			for(int j=1;j<=n;j++){
      				f[u][i]=min(f[u][i],tmp+f[v][j]);
      			}
      		}
      	}
      }
      il void dfs2(int u,int fa){
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		int res=inf;
      		for(int i=1;i<=n;i++){
      			if(res>f[v][i]){
      				res=f[v][i],ans[v]=i;
      			}
      		}
      		if(f[v][ans[u]]-m<f[v][ans[v]]){
      			ans[v]=ans[u];
      		}
      		dfs2(v,u);
      	}
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      signed main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=1;i<n;i++){
      		cin>>a[i];
      	}
      	memset(dis,0x3f,sizeof dis);
      	for(int i=1;i<=n;i++){
      		dis[i][i]=0;
      	}
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      		dis[u][v]=dis[v][u]=1;
      	}
      	for(int k=1;k<=n;k++){
      		for(int i=1;i<=n;i++){
      			for(int j=1;j<=n;j++){
      				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
      			}
      		}
      	}
      //	for(int i=1;i<=n;i++){
      //		for(int j=1;j<=n;j++){
      //			cout<<dis[i][j]<<" ";
      //		}
      //		puts("");
      //	}
      	dfs1(1,0);
      //	for(int i=1;i<=n;i++){
      //		for(int j=1;j<=n;j++){
      //			printf("%2d ",f[i][j]);
      //		}
      //		puts("");
      //	}
      	int res=inf;
      	for(int i=1;i<=n;i++){
      		if(res>f[1][i]){
      			res=f[1][i],ans[1]=i;
      		}
      	}
      	cout<<res<<"\n";
      	dfs2(1,0);
      	for(int i=1;i<=n;i++){
      		cout<<ans[i]<<" ";
      	}
      	return 0;
      }
      }
      signed main(){return asbt::main();}
      

      C. 「JZOI-1」旅行

      考慮一次詢問,顯然 DP,設 \(f_{u,0/1}\) 表示走路/坐船到 \(u\) 點的最小花費即可。
      多次詢問,考慮維護矩陣,廣義矩陣乘,倍增處理詢問。對每個點 \(u\) 維護 \(up_{u,i}\)\(dw_{u,i}\) 表示從 \(u\) 向上走到 \(2^i\) 級祖先的矩陣和從 \(2^i\) 級祖先向下走到 \(u\) 的矩陣。時間復雜度 \(O((n+t)\log n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=2e5+5;
      const ll inf=0x3f3f3f3f3f3f3f3f;
      int n,m,q,enm,hd[maxn];
      int anc[maxn][22],dep[maxn];
      struct edge{
      	int v,nxt;
      	ll w,d;
      	bool typ;
      }e[maxn<<1];
      il void addedge(int u,int v,ll w,ll d,bool typ){
      	e[++enm]=(edge){v,hd[u],w,d,typ};
      	hd[u]=enm;
      }
      struct juz{
      	ll mat[2][2];
      	juz(){
      		mat[0][0]=mat[0][1]=mat[1][0]=mat[1][1]=0;
      	}
      	il ll*operator[](int x){
      		return mat[x];
      	}
      	il juz operator*(juz x)const{
      		juz res;
      		res[0][0]=res[0][1]=res[1][0]=res[1][1]=inf;
      		for(int i=0;i<=1;i++){
      			for(int j=0;j<=1;j++){
      				for(int k=0;k<=1;k++){
      					res[i][j]=min(res[i][j],mat[i][k]+x[k][j]);
      				}
      			}
      		}
      		return res;
      	}
      }up[maxn][22],dw[maxn][22];
      il void dfs(int u,int fa){
      	anc[u][0]=fa,dep[u]=dep[fa]+1;
      	for(int i=1;i<=20;i++){
      		anc[u][i]=anc[anc[u][i-1]][i-1];
      		up[u][i]=up[u][i-1]*up[anc[u][i-1]][i-1];
      		dw[u][i]=dw[anc[u][i-1]][i-1]*dw[u][i-1];
      	}
      	for(int i=hd[u],v,w,d,typ;i;i=e[i].nxt){
      		v=e[i].v,w=e[i].w,d=e[i].d,typ=e[i].typ;
      		if(v==fa){
      			continue;
      		}
      		up[v][0][0][0]=up[v][0][1][0]=w;
      		dw[v][0][0][0]=dw[v][0][1][0]=w;
      		if(typ){
      			up[v][0][0][1]=m+w+d;
      			up[v][0][1][1]=w+d;
      			dw[v][0][0][1]=m+w-d;
      			dw[v][0][1][1]=w-d;
      		}
      		else{
      			up[v][0][0][1]=m+w-d;
      			up[v][0][1][1]=w-d;
      			dw[v][0][0][1]=m+w+d;
      			dw[v][0][1][1]=w+d;
      		}
      		dfs(v,u);
      	}
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m>>q;
      	for(int i=1,u,v,w,d,typ;i<n;i++){
      		cin>>u>>v>>w>>d>>typ;
      		addedge(u,v,w,d,typ);
      		addedge(v,u,w,d,typ^1);
      	}
      	dfs(1,0);
      //	for(int i=1;i<=n;i++){
      //		for(int j=0;j<=1;j++){
      //			cout<<up[i][j][0][0]<<" "<<up[i][j][0][1]<<" ";
      //		}
      //		puts("");
      //		for(int j=0;j<=1;j++){
      //			cout<<up[i][j][1][0]<<" "<<up[i][j][1][1]<<" ";
      //		}
      //		puts("");
      //	}
      //	for(int i=1;i<=n;i++){
      //		for(int j=0;j<=1;j++){
      //			cout<<dw[i][j][0][0]<<" "<<dw[i][j][0][1]<<" ";
      //		}
      //		puts("");
      //		for(int j=0;j<=1;j++){
      //			cout<<dw[i][j][1][0]<<" "<<dw[i][j][1][1]<<" ";
      //		}
      //		puts("");
      //	}
      	while(q--){
      		int u,v;
      		cin>>u>>v;
      		if(u==v){
      			cout<<"0\n";
      			continue;
      		}
      		juz resu,resv;
      		bool flu=0,flv=0;
      		if(dep[u]>dep[v]){
      			int ddep=dep[u]-dep[v],tmp=0;
      			while(ddep){
      				if(ddep&1){
      					if(!flu){
      						resu=up[u][tmp];
      						flu=1;
      					}
      					else{
      						resu=resu*up[u][tmp];
      					}
      					u=anc[u][tmp];
      				}
      				ddep>>=1,tmp++;
      			}
      			if(u==v){
      				cout<<min(resu[0][0],resu[0][1])<<"\n";
      				continue;
      			}
      		}
      		else{
      			int ddep=dep[v]-dep[u],tmp=0;
      			while(ddep){
      				if(ddep&1){
      					if(!flv){
      						resv=dw[v][tmp];
      						flv=1;
      					}
      					else{
      						resv=dw[v][tmp]*resv;
      					}
      					v=anc[v][tmp];
      				}
      				ddep>>=1,tmp++;
      			}
      			if(u==v){
      				cout<<min(resv[0][0],resv[0][1])<<"\n";
      				continue;
      			}
      		}
      //		for(int i=0;i<=1;i++){
      //			for(int j=0;j<=1;j++){
      //				cout<<resu[i][j]<<" ";
      //			}
      //			puts("");
      //		}
      //		for(int i=0;i<=1;i++){
      //			for(int j=0;j<=1;j++){
      //				cout<<resv[i][j]<<" ";
      //			}
      //			puts("");
      //		}
      		for(int i=20;~i;i--){
      			if(anc[u][i]!=anc[v][i]){
      				if(!flu){
      					resu=up[u][i];
      					flu=1;
      				}
      				else{
      					resu=resu*up[u][i];
      				}
      				if(!flv){
      					resv=dw[v][i];
      					flv=1;
      				}
      				else{
      					resv=dw[v][i]*resv;
      				}
      				u=anc[u][i],v=anc[v][i];
      			}
      		}
      		if(!flu){
      			resu=up[u][0];
      		}
      		else{
      			resu=resu*up[u][0];
      		}
      		if(!flv){
      			resv=dw[v][0];
      		}
      		else{
      			resv=dw[v][0]*resv;
      		}
      		juz res=resu*resv;
      		cout<<min(res[0][0],res[0][1])<<"\n";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      D. 「DBOI」Round 1 人生如樹

      新加的點不會影響之前的詢問,所以直接離線,先把所有點都建好。
      將問題轉化為:用 \(b\) 數組減去 \(a\) 數組,得到的形如 \(1,2,3,\dots\) 的等差序列的最大長度。
      考慮將兩個序列哈希,預處理出等差數列的哈希值,二分長度即可。而在樹上維護路徑數組的哈希值,可以用倍增解決。
      時間復雜度 \(O(m\log^2n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define ull unsigned ll
      #define pb push_back
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=2e5+5;
      const ull bas1=13331;
      const ll bas2=13327,mod2=1e9+7;
      int n,m,q,T,_2[22];
      int a[maxn],dep[maxn];
      int anc[maxn][22];
      vector<int> e[maxn];
      struct wnti{
      	int u1,v1,u2,v2;
      }wt[maxn];
      ull tar1[maxn],pw1[maxn];
      ull up1[maxn][22],dw1[maxn][22];
      ll tar2[maxn],pw2[maxn];
      ll up2[maxn][22],dw2[maxn][22];
      il void dfs(int u,int fa){
      	anc[u][0]=fa,dep[u]=dep[fa]+1;
      	up1[u][0]=dw1[u][0]=a[u]*pw1[1];
      	up2[u][0]=dw2[u][0]=a[u]*pw2[1]%mod2;
      	for(int i=1;i<=20;i++){
      		anc[u][i]=anc[anc[u][i-1]][i-1];
      		up1[u][i]=up1[u][i-1]+up1[anc[u][i-1]][i-1]*pw1[_2[i-1]];
      		dw1[u][i]=dw1[u][i-1]*pw1[_2[i-1]]+dw1[anc[u][i-1]][i-1];
      		up2[u][i]=(up2[u][i-1]+up2[anc[u][i-1]][i-1]*pw2[_2[i-1]])%mod2;
      		dw2[u][i]=(dw2[u][i-1]*pw2[_2[i-1]]+dw2[anc[u][i-1]][i-1])%mod2;
      	}
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		dfs(v,u);
      	}
      }
      il int lca(int u,int v){
      	if(dep[u]<dep[v]){
      		swap(u,v);
      	}
      	int ddep=dep[u]-dep[v],tmp=0;
      	while(ddep){
      		if(ddep&1){
      			u=anc[u][tmp];
      		}
      		ddep>>=1,tmp++;
      	}
      	if(u==v){
      		return u;
      	}
      	for(int i=20;~i;i--){
      		if(anc[u][i]!=anc[v][i]){
      			u=anc[u][i],v=anc[v][i];
      		}
      	}
      	return anc[u][0];
      }
      il int ganc(int u,int k){
      	int tmp=0;
      	while(k){
      		if(k&1){
      			u=anc[u][tmp];
      		}
      		k>>=1,tmp++;
      	}
      	return u;
      }
      il ull gha1(int u,int v,int rt,int len){
      //	cout<<u<<" "<<v<<"\n";
      	if(len<=dep[u]-dep[rt]+1){
      		int tmp=0,cur=0;
      		ull res=0;
      		while(len){
      			if(len&1){
      				res+=up1[u][tmp]*pw1[cur];
      				cur+=_2[tmp],u=anc[u][tmp];
      			}
      			len>>=1,tmp++;
      		}
      //		cout<<res<<"\n";
      		return res;
      	}
      	int ddep=dep[u]-dep[rt]+1;
      	int tmp=0,cur=0;
      	ull res=0;
      	len-=ddep;
      	int tdep=ddep;
      	while(ddep){
      		if(ddep&1){
      			res+=up1[u][tmp]*pw1[cur];
      			cur+=_2[tmp],u=anc[u][tmp];
      		}
      		ddep>>=1,tmp++;
      	}
      	v=ganc(v,dep[v]-dep[rt]-len);
      //	cout<<v<<" "<<res<<"\n";
      	tmp=cur=0;
      	int tlen=len;
      	while(len){
      		if(len&1){
      			res+=dw1[v][tmp]*pw1[tdep+tlen-cur-_2[tmp]];
      			cur+=_2[tmp],v=anc[v][tmp];
      		}
      		len>>=1,tmp++;
      	}
      //	cout<<res<<"\n";
      	return res;
      }
      il ll gha2(int u,int v,int rt,int len){
      	if(len<=dep[u]-dep[rt]+1){
      		int tmp=0,cur=0;
      		ll res=0;
      		while(len){
      			if(len&1){
      				(res+=up2[u][tmp]*pw2[cur])%=mod2;
      				cur+=_2[tmp],u=anc[u][tmp];
      			}
      			len>>=1,tmp++;
      		}
      		return res;
      	}
      	int ddep=dep[u]-dep[rt]+1;
      	int tmp=0,cur=0;
      	ll res=0;
      	len-=ddep;
      	int tdep=ddep;
      	while(ddep){
      		if(ddep&1){
      			(res+=up2[u][tmp]*pw2[cur])%=mod2;
      			cur+=_2[tmp],u=anc[u][tmp];
      		}
      		ddep>>=1,tmp++;
      	}
      	v=ganc(v,dep[v]-dep[rt]-len);
      	tmp=cur=0;
      	int tlen=len;
      	while(len){
      		if(len&1){
      			(res+=dw2[v][tmp]*pw2[tdep+tlen-cur-_2[tmp]])%=mod2;
      			cur+=_2[tmp],v=anc[v][tmp];
      		}
      		len>>=1,tmp++;
      	}
      	return res;
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m>>T;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      	}
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      	}
      	while(m--){
      		int opt;
      		cin>>opt;
      		if(opt==1){
      			int u1,v1,u2,v2;
      			cin>>u1>>v1>>u2>>v2;
      			wt[++q]=(wnti){u1,v1,u2,v2};
      		}
      		else{
      			int u,w;
      			cin>>u>>w;
      			a[++n]=w;
      			e[u].pb(n),e[n].pb(u);
      		}
      	}
      	pw1[0]=pw2[0]=1;
      	for(int i=1;i<=n;i++){
      		pw1[i]=pw1[i-1]*bas1;
      		pw2[i]=pw2[i-1]*bas2%mod2;
      		tar1[i]=tar1[i-1]+i*pw1[i];
      		tar2[i]=(tar2[i-1]+i*pw2[i])%mod2;
      	}
      	_2[0]=1;
      	for(int i=1;i<=20;i++){
      		_2[i]=_2[i-1]<<1;
      	}
      	dfs(1,0);
      //	for(int u=1;u<=n;u++){
      //		for(int i=0;i<=2;i++){
      //			cout<<anc[u][i]<<" ";
      //		}
      //		puts("");
      //	}
      	for(int i=1,u1,v1,u2,v2,rt1,rt2,l,r;i<=q;i++){
      		u1=wt[i].u1,v1=wt[i].v1;
      		u2=wt[i].u2,v2=wt[i].v2;
      		rt1=lca(u1,v1),rt2=lca(u2,v2);
      		l=0;
      		r=min(dep[u1]+dep[v1]-2*dep[rt1],dep[u2]+dep[v2]-2*dep[rt2])+1;
      //		cout<<l<<" "<<r<<"\n";
      		while(l<r){
      			int mid=(l+r+1)>>1;
      //			cout<<l<<" "<<r<<" "<<mid<<"\n";
      			if(gha1(u2,v2,rt2,mid)-gha1(u1,v1,rt1,mid)==tar1[mid]&&(gha2(u2,v2,rt2,mid)-gha2(u1,v1,rt1,mid)+mod2)%mod2==tar2[mid]){
      				l=mid;
      			}
      			else{
      				r=mid-1;
      			}
      		}
      		cout<<l<<"\n";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      E. Mobile Phone Network

      首先強制選擇那 \(k\) 條邊跑最小生成樹。然后用非樹邊限制路徑上的邊。時間復雜度 \(O(m\log^2n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pii pair<int,int>
      #define mp make_pair
      #define fir first
      #define sec second
      #define pb push_back
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      namespace IO{
      	const int bufsz=1<<20;
      	char ibuf[bufsz],*p1=ibuf,*p2=ibuf;
      	#define getchar() (p1==p2&&(p2=(p1=ibuf)+fread(ibuf,1,bufsz,stdin),p1==p2)?EOF:*p1++)
      	il int read(){
      		char ch=getchar();
      		while(ch<'0'||ch>'9'){
      			ch=getchar();
      		}
      		int x=0;
      		while(ch>='0'&&ch<='9'){
      			x=(x<<1)+(x<<3)+(ch^48);
      			ch=getchar();
      		}
      		return x;
      	}
      	#undef getchar
      	char obuf[bufsz],*p3=obuf,s[50];
      	#define flush() (fwrite(obuf,1,p3-obuf,stdout),p3=obuf)
      	#define putchar(ch) (p3==obuf+bufsz&&flush(),*p3++=(ch))
      	il void write(ll x){
      		if(x<0){
      			putchar('-');
      			x=-x;
      		}
      		int top=0;
      		do{
      			s[++top]=x%10|48;
      			x/=10;
      		}while(x);
      		while(top){
      			putchar(s[top--]);
      		}
      		putchar('\n');
      	}
      	#undef putchar
      	class Flush{
      		public:
      		~Flush(){
      			flush();
      		}
      	}FL;
      	#undef flush
      }
      using IO::read;
      using IO::write;
      const int maxn=5e5+5;
      const int inf=0x3f3f3f3f;
      int n,k,m,cnt,fa[maxn],sz[maxn];
      int hes[maxn],dep[maxn],top[maxn];
      int dfn[maxn],idx[maxn],tofa[maxn];
      int zhi[maxn<<2];
      bool vis[maxn];
      vector<pii> e[maxn];
      struct edge{
      	int u,v,w;
      	il bool operator<(const edge &x)const{
      		return w<x.w;
      	}
      }a[maxn];
      il int find(int x){
      	return x!=fa[x]?fa[x]=find(fa[x]):x;
      }
      il void merge(int u,int v){
      	u=find(u),v=find(v);
      	if(u==v){
      		return ;
      	}
      	if(sz[u]>sz[v]){
      		sz[u]+=sz[v],fa[v]=u;
      	}
      	else{
      		sz[v]+=sz[u],fa[u]=v;
      	}
      }
      il void dfs1(int u){
      //	cout<<u<<"\n";
      //	puts("666");
      	sz[u]=1;
      	int mxs=0;
      	for(pii i:e[u]){
      		int v=i.fir,w=i.sec;
      		if(v==fa[u]){
      			continue;
      		}
      		fa[v]=u,tofa[v]=w;
      		dep[v]=dep[u]+1;
      		dfs1(v);
      		sz[u]+=sz[v];
      		if(mxs<sz[v]){
      			mxs=sz[v],hes[u]=v;
      		}
      	}
      }
      il void dfs2(int u){
      	dfn[u]=++cnt,idx[cnt]=u;
      	if(!top[u]){
      		top[u]=u;
      	}
      	if(hes[u]){
      		top[hes[u]]=top[u];
      		dfs2(hes[u]);
      	}
      	for(pii i:e[u]){
      		int v=i.fir,w=i.sec;
      		if(v==fa[u]||v==hes[u]){
      			continue;
      		}
      		dfs2(v);
      	}
      }
      il void build(int id,int l,int r){
      	if(l==r){
      		zhi[id]=tofa[idx[l]];
      		return ;
      	}
      	zhi[id]=inf;
      	int mid=(l+r)>>1;
      	build(lid,l,mid);
      	build(rid,mid+1,r);
      }
      il void upd(int id,int L,int R,int l,int r,int v){
      	if(l>r){
      		return ;
      	}
      	if(L>=l&&R<=r){
      		zhi[id]=min(zhi[id],v);
      		return ;
      	}
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		upd(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		upd(rid,mid+1,R,l,r,v);
      	}
      }
      il int query(int id,int l,int r,int p){
      	if(l==r){
      		return zhi[id];
      	}
      	int mid=(l+r)>>1;
      	if(p<=mid){
      		return min(zhi[id],query(lid,l,mid,p));
      	}
      	return min(zhi[id],query(rid,mid+1,r,p));
      }
      il void upd(int u,int v,int w){
      	while(top[u]!=top[v]){
      		if(dep[top[u]]<dep[top[v]]){
      			swap(u,v);
      		}
      		upd(1,1,n,dfn[top[u]],dfn[u],w);
      		u=fa[top[u]];
      	}
      	if(dep[u]>dep[v]){
      		swap(u,v);
      	}
      	upd(1,1,n,dfn[u]+1,dfn[v],w);
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      signed main(){
      //	freopen("E.in","r",stdin);
      	n=read(),k=read(),m=read();
      	for(int i=1;i<=n;i++){
      		fa[i]=i,sz[i]=1;
      	}
      	for(int i=1,u,v;i<=k;i++){
      		u=read(),v=read();
      		e[u].pb(mp(v,inf));
      		e[v].pb(mp(u,inf));
      		merge(u,v);
      	}
      	for(int i=1;i<=m;i++){
      		a[i].u=read(),a[i].v=read(),a[i].w=read();
      	}
      	sort(a+1,a+m+1);
      	for(int i=1,u,v;i<=m;i++){
      		u=a[i].u,v=a[i].v;
      		if(find(u)!=find(v)){
      			merge(u,v);
      			vis[i]=1;
      			e[u].pb(mp(v,0));
      			e[v].pb(mp(u,0));
      		}
      	}
      	for(int i=1;i<=n;i++){
      		fa[i]=0;
      	}
      	dfs1(1),dfs2(1);
      //	puts("666");
      	build(1,1,n);
      	for(int i=1;i<=m;i++){
      		if(!vis[i]){
      			upd(a[i].u,a[i].v,a[i].w);
      		}
      	}
      	ll ans=0;
      	for(int i=1,res;i<=n;i++){
      		res=query(1,1,n,i);
      		if(res>=inf){
      			write(-1);
      			return 0;
      		}
      		ans+=res;
      	}
      	write(ans);
      	return 0;
      }
      }
      signed main(){return asbt::main();}
      

      F. Close Vertices

      點分治,對于每個子樹中的點按照到重心的邊權和排序,用雙指針維護邊權和的限制,用樹狀數組維護邊數限制。時間復雜度 \(O(n\log^2n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pb push_back
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e5+5;
      const int inf=0x3f3f3f3f;
      int n,m,k,enm=1,hd[maxn];
      int sz[maxn],mxs[maxn];
      int dep[maxn],dis[maxn];
      bool ban[maxn<<1];
      vector<int> curd;
      struct edge{
      	int v,nxt,w;
      }e[maxn<<1];
      il void addedge(int u,int v,int w){
      	e[++enm]=(edge){v,hd[u],w};
      	hd[u]=enm;
      }
      struct{
      	int tr[maxn];
      	il int lowbit(int x){
      		return x&-x;
      	}
      	il void upd(int p,int v){
      		for(;p<=n+1;p+=lowbit(p)){
      			tr[p]+=v;
      		}
      	}
      	il int query(int p){
      		int res=0;
      		for(;p;p-=lowbit(p)){
      			res+=tr[p];
      		}
      		return res;
      	}
      }F;
      il void dfs1(int u,int fa,int tot){
      	sz[u]=1,mxs[u]=0;
      	for(int i=hd[u],v;i;i=e[i].nxt){
      		v=e[i].v;
      		if(v==fa||ban[i]){
      			continue;
      		}
      		dfs1(v,u,tot);
      		sz[u]+=sz[v];
      		mxs[u]=max(mxs[u],sz[v]);
      	}
      	mxs[u]=max(mxs[u],tot-sz[u]);
      }
      il void dfs2(int u,int fa){
      	for(int i=hd[u],v,w;i;i=e[i].nxt){
      		v=e[i].v,w=e[i].w;
      		if(v==fa||ban[i]){
      			continue;
      		}
      		dep[v]=dep[u]+1,dis[v]=dis[u]+w;
      		dfs2(v,u);
      	}
      }
      il ll gans(){
      	sort(curd.begin(),curd.end(),[](const int x,const int y){return dis[x]<dis[y];});
      	for(int u:curd){
      		F.upd(dep[u]+1,1);
      //		cout<<u<<" "<<dep[u]<<" "<<dis[u]<<"\n";
      	}
      	int l=0,r=curd.size()-1;
      	ll res=0;
      	while(l<r){
      		if(dis[curd[l]]+dis[curd[r]]<=k){
      			F.upd(dep[curd[l]]+1,-1);
      			res+=F.query(max(m-dep[curd[l++]]+1,0));
      		}
      		else{
      			F.upd(dep[curd[r--]]+1,-1);
      		}
      	}
      	F.upd(dep[curd[l]]+1,-1);
      	return res;
      }
      il void dfs3(int u,int fa){
      	curd.pb(u);
      	for(int i=hd[u],v;i;i=e[i].nxt){
      		v=e[i].v;
      		if(v==fa||ban[i]){
      			continue;
      		}
      		dfs3(v,u);
      	}
      }
      il ll solve(){
      	if(curd.size()==1){
      		return 0;
      	}
      	dfs1(curd.front(),0,curd.size());
      	int rt=0,mmx=inf;
      	for(int u:curd){
      		if(mmx>mxs[u]){
      			mmx=mxs[u],rt=u;
      		}
      	}
      //	cout<<rt<<"\n";
      	dep[rt]=dis[rt]=0;
      	dfs2(rt,0);
      	ll res=0;
      	res+=gans();
      //	cout<<res<<"\n";
      	for(int i=hd[rt],v;i;i=e[i].nxt){
      		if(ban[i]){
      			continue;
      		}
      		v=e[i].v;
      		curd.clear();
      		dfs3(v,rt);
      		res-=gans();
      	}
      	for(int i=hd[rt],v;i;i=e[i].nxt){
      		if(ban[i]){
      			continue;
      		}
      		v=e[i].v;
      		ban[i]=ban[i^1]=1;
      		curd.clear();
      		dfs3(v,0);
      		res+=solve();
      	}
      	return res;
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      //	cout<<cplx::usdmem();
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m>>k;
      	for(int i=2,u,w;i<=n;i++){
      		cin>>u>>w;
      		addedge(u,i,w);
      		addedge(i,u,w);
      	}
      	for(int i=1;i<=n;i++){
      		curd.pb(i);
      	}
      	cout<<solve()<<"\n";
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      G. Nastia Plays with a Tree

      構造題,從下往上構造,將每個子樹都連成一條鏈。
      鏈分為兩種:

      1. 以根為一頭的鏈
      2. 跨過根的鏈

      對于一個節點 \(u\),若它的兒子中沒有或只有一個 \(1\) 號鏈,那就把其它兒子接上去,將 \(u\) 的子樹變為 \(1\) 號鏈;否則就保留 \(2\) 個子樹,將 \(u\) 的子樹變為 \(2\) 號鏈。
      時間復雜度 \(O(n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pb push_back
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e5+5;
      int T,n;
      vector<int> e[maxn],curd[maxn];
      struct{
      	int a,b,typ;
      }zis[maxn];
      struct node{
      	int a,b,c,d;
      };
      vector<node> ans;
      il void dfs(int u,int fa){
      //	cout<<u<<"\n";
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      //		cout<<u<<" "<<v<<"\n";
      		dfs(v,u);
      		curd[u].pb(v);
      	}
      //	puts("");
      	zis[u].typ=1,zis[u].a=u;
      	sort(curd[u].begin(),curd[u].end(),[](const int &x,const int &y){return zis[x].typ<zis[y].typ;});
      	int cnt=0;
      	for(int v:curd[u]){
      		if(zis[v].typ==1){
      			cnt++;
      		}
      		else{
      			break;
      		}
      	}
      //	cout<<u<<" "<<curd.size()<<"\n";
      	if(!cnt){
      		for(int v:curd[u]){
      			ans.pb((node){u,v,zis[u].a,zis[v].a});
      			zis[u].a=zis[v].b;
      		}
      	}
      	else if(cnt==1){
      		zis[u].a=zis[curd[u][0]].a;
      		for(int i=1,v;i<curd[u].size();i++){
      			v=curd[u][i];
      			ans.pb((node){u,v,zis[u].a,zis[v].a});
      			zis[u].a=zis[v].b;
      		}
      	}else{
      		zis[u].typ=2;
      		zis[u].a=zis[curd[u][0]].a;
      		zis[u].b=zis[curd[u][1]].a;
      		for(int i=2,v;i<curd[u].size();i++){
      			v=curd[u][i];
      			if(zis[v].typ==1){
      				ans.pb((node){u,v,zis[u].a,v});
      				zis[u].a=zis[v].a;
      			}
      			else{
      				ans.pb((node){u,v,zis[u].a,zis[v].a});
      				zis[u].a=zis[v].b;
      			}
      		}
      	}
      }
      il void solve(){
      	cin>>n;
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      	}
      	ans.clear();
      	dfs(1,0);
      	for(int i=1;i<=n;i++){
      //		cout<<i<<" "<<zis[i].typ<<" "<<zis[i].a<<" "<<zis[i].b<<"\n";
      	}
      	cout<<ans.size()<<"\n";
      	for(node i:ans){
      		cout<<i.a<<" "<<i.b<<" "<<i.c<<" "<<i.d<<"\n";
      	}
      	for(int i=1;i<=n;i++){
      		e[i].clear();
      		curd[i].clear();
      	}
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>T;
      	while(T--){
      		solve();
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      H. [ARC165E] Random Isolation

      考慮將操作改為任選一個排列 \(p\),從 \(1\)\(n\) 依次操作,如果 \(p_i\) 所在的連通塊大小大于 \(k\),那么就刪掉,否則就不刪。這樣的轉化是正確的,因為當前 \(i-1\) 個位置相同時,當前可操作的點出現在 \(p_i\) 的概率是相等的。
      考慮一個大小為 \(x\) 的連通塊,它連向外面的邊數為 \(y\),這個局面出現的概率就是 \(\frac{x!y!}{(x+y)!}\)。因此我們需要計數每種局面的數量。
      \(f_{u,i,j}\) 表示 \(u\) 的子樹內,強制選 \(u\),選了 \(i\) 個點,向外(除了 \(fa_u\))連了 \(j\) 條邊的數量。背包轉移即可。時間復雜度 \(O(n^4)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pb push_back
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=105,mod=998244353;
      int n,m,sz[maxn];
      int nf[maxn][maxn];
      int f[maxn][maxn][maxn];
      int fac[maxn<<1],inv[maxn<<1];
      vector<int> e[maxn];
      il int qpow(int x,int y){
      	int res=1;
      	while(y){
      		if(y&1){
      			res=res*1ll*x%mod;
      		}
      		y>>=1,x=x*1ll*x%mod;
      	}
      	return res;
      }
      il void dfs(int u,int fa){
      	f[u][1][0]=sz[u]=1;
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		dfs(v,u);
      		for(int i=0;i<=sz[u]+sz[v];i++){
      			for(int j=0;j<=sz[u]+sz[v];j++){
      				nf[i][j]=0;
      			}
      		}
      		for(int i=0;i<=sz[u];i++){
      			for(int j=0;j<=sz[u];j++){
      				for(int x=0;x<=sz[v];x++){
      					for(int y=0;y<=sz[v];y++){
      						(nf[i+x][j+y]+=f[u][i][j]*1ll*f[v][x][y]%mod)%=mod;
      					}
      				}
      			}
      		}
      		sz[u]+=sz[v];
      		for(int i=0;i<=sz[u];i++){
      			for(int j=0;j<=sz[u];j++){
      				f[u][i][j]=nf[i][j];
      			}
      		}
      	}
      	f[u][0][1]=1;
      }
      il void init(int x){
      	fac[0]=1;
      	for(int i=1;i<=x;i++){
      		fac[i]=fac[i-1]*1ll*i%mod;
      	}
      	inv[x]=qpow(fac[x],mod-2);
      	for(int i=x;i;i--){
      		inv[i-1]=inv[i]*1ll*i%mod;
      	}
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      	}
      	dfs(1,0),init(n<<1);
      //	for(int i=1;i<=n;i++){
      //		cout<<fac[i]<<" "<<fac[i]*1ll*inv[i]%mod<<"\n";
      //	}
      	int ans=0;
      	for(int u=1;u<=n;u++){
      		for(int i=m+1;i<=sz[u];i++){
      			for(int j=0,k;j<=sz[u];j++){
      				k=j;
      				if(u!=1){
      					k++;
      				}
      				(ans+=f[u][i][j]*1ll*fac[i]%mod*fac[k]%mod*inv[i+k]%mod)%=mod;
      			}
      		}
      	}
      	cout<<ans;
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      I. 「LNOI2014」LCA

      圖論相關問題 B。

      Code
      #include<bits/stdc++.h>
      #define int long long
      #define il inline
      #define pb push_back
      #define pii pair<int,int>
      #define mp make_pair
      #define fir first
      #define sec second
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=5e4+5,mod=201314;
      int n,m,fa[maxn],sz[maxn];
      int hes[maxn],top[maxn];
      int dfn[maxn],cnt,ans[maxn];
      int sum[maxn<<2],tag[maxn<<2];
      vector<int> e[maxn];
      vector<pii> wt[maxn];
      il void dfs1(int u){
      	sz[u]=1;
      	int mxs=0;
      	for(int v:e[u]){
      		dfs1(v);
      		sz[u]+=sz[v];
      		if(mxs<sz[v]){
      			mxs=sz[v],hes[u]=v;
      		}
      	}
      }
      il void dfs2(int u){
      	dfn[u]=++cnt;
      	if(!top[u]){
      		top[u]=u;
      	}
      	if(hes[u]){
      		top[hes[u]]=top[u];
      		dfs2(hes[u]);
      	}
      	for(int v:e[u]){
      		if(v==hes[u]){
      			continue;
      		}
      		dfs2(v);
      	}
      }
      il void pushup(int id){
      	sum[id]=sum[lid]+sum[rid];
      }
      il void pushtag(int id,int l,int r,int v){
      	tag[id]+=v;
      	sum[id]+=(r-l+1)*v;
      }
      il void pushdown(int id,int l,int r){
      	if(tag[id]){
      		int mid=(l+r)>>1;
      		pushtag(lid,l,mid,tag[id]);
      		pushtag(rid,mid+1,r,tag[id]);
      		tag[id]=0;
      	}
      }
      il void upd(int id,int L,int R,int l,int r,int v){
      	if(L>=l&&R<=r){
      		pushtag(id,L,R,v);
      		return ;
      	}
      	pushdown(id,L,R);
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		upd(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		upd(rid,mid+1,R,l,r,v);
      	}
      	pushup(id);
      }
      il int query(int id,int L,int R,int l,int r){
      	if(L>=l&&R<=r){
      		return sum[id];
      	}
      	pushdown(id,L,R);
      	int mid=(L+R)>>1,res=0;
      	if(l<=mid){
      		res+=query(lid,L,mid,l,r);
      	}
      	if(r>mid){
      		res+=query(rid,mid+1,R,l,r);
      	}
      	return res;
      }
      il void upd(int u){
      	while(u){
      		upd(1,1,n,dfn[top[u]],dfn[u],1);
      		u=fa[top[u]];
      	}
      }
      il int query(int u){
      	int res=0;
      	while(u){
      		res+=query(1,1,n,dfn[top[u]],dfn[u]);
      		u=fa[top[u]];
      	}
      	return res;
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      signed main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=2;i<=n;i++){
      		cin>>fa[i];
      		fa[i]++;
      		e[fa[i]].pb(i);
      	}
      	dfs1(1),dfs2(1);
      	for(int i=1,l,r,u;i<=m;i++){
      		cin>>l>>r>>u;
      		r++,u++;
      		wt[l].pb(mp(u,-i));
      		wt[r].pb(mp(u,i));
      	}
      	for(int i=1;i<=n;i++){
      		upd(i);
      		for(pii j:wt[i]){
      			if(j.sec>0){
      				ans[j.sec]+=query(j.fir);
      			}
      			else{
      				ans[-j.sec]-=query(j.fir);
      			}
      		}
      	}
      	for(int i=1;i<=m;i++){
      		cout<<ans[i]%mod<<"\n";
      	}
      	return 0;
      }
      }
      signed main(){return asbt::main();}
      

      J. Tree and Queries

      考慮記錄每個數量的顏色數,用樹狀數組查詢。
      對于每個子樹,拍到 dfs 序上后就是一個區間。因此莫隊即可。時間復雜度 \(O(n\sqrt{n}\log n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pb push_back
      #define pii pair<int,int>
      #define mp make_pair
      #define fir first
      #define sec second
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e5+5;
      int n,m,a[maxn],ans[maxn];
      int sz[maxn],dfn[maxn];
      int cnt,idx[maxn],buc[maxn];
      int blen,bel[maxn];
      vector<int> e[maxn];
      vector<pii> wt[maxn];
      il void dfs(int u,int fa){
      	dfn[u]=++cnt;
      	idx[cnt]=a[u];
      	sz[u]=1;
      	for(int v:e[u]){
      		if(v!=fa){
      			dfs(v,u);
      			sz[u]+=sz[v];
      		}
      	}
      }
      struct wnti{
      	int l,r,u;
      	il bool operator<(const wnti &x)const{
      		if(bel[l]==bel[x.l]){
      			return bel[l]&1?r>x.r:r<x.r;
      		}
      		return l<x.l;
      	}
      }wnt[maxn];
      struct{
      	int tr[maxn];
      	il int lowbit(int x){
      		return x&-x;
      	}
      	il void upd(int p,int v){
      		for(;p<=n;p+=lowbit(p)){
      			tr[p]+=v;
      		}
      	}
      	il int query(int p){
      		int res=0;
      		for(;p;p-=lowbit(p)){
      			res+=tr[p];
      		}
      		return res;
      	}
      }F;
      il void add(int x){
      	if(buc[x]){
      		F.upd(buc[x],-1);
      	}
      	F.upd(++buc[x],1);
      }
      il void del(int x){
      	F.upd(buc[x]--,-1);
      	if(buc[x]){
      		F.upd(buc[x],1);
      	}
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      	}
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      	}
      	for(int i=1,u,k;i<=m;i++){
      		cin>>u>>k;
      		if(k>n){
      			k=n+1;
      		}
      		wt[u].pb(mp(k,i));
      	}
      	dfs(1,0);
      //	puts("666");
      	for(int i=1;i<=n;i++){
      		wnt[i]=(wnti){dfn[i],dfn[i]+sz[i]-1,i};
      	}
      	blen=sqrt(n);
      	for(int i=1;i<=n;i++){
      		bel[i]=i/blen;
      	}
      	sort(wnt+1,wnt+n+1);
      	int l=1,r=0;
      	for(int i=1;i<=n;i++){
      		while(l>wnt[i].l){
      			add(idx[--l]);
      		}
      		while(r<wnt[i].r){
      			add(idx[++r]);
      		}
      		while(l<wnt[i].l){
      			del(idx[l++]);
      		}
      		while(r>wnt[i].r){
      			del(idx[r--]);
      		}
      		for(pii j:wt[wnt[i].u]){
      			ans[j.sec]=F.query(n)-F.query(j.fir-1);
      		}
      	}
      	for(int i=1;i<=m;i++){
      		cout<<ans[i]<<"\n";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      
      posted @ 2025-02-08 19:14  zhangxy__hp  閱讀(30)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲另类无码一区二区三区| 国产精品国产三级国av| 精品人妻av中文字幕乱| 国产无遮挡免费真人视频在线观看| 99精品高清在线播放| 亚洲男女羞羞无遮挡久久丫| 超碰成人人人做人人爽| 一区二区和激情视频| 欧美z0zo人禽交另类视频| 中文字幕人妻无码一夲道| 亚洲2022国产成人精品无码区 | 婷婷六月色| 福利视频在线一区二区| 桃园市| 麻豆精品一区二区综合av| 美女黄18以下禁止观看| 国产精品亚洲中文字幕| 城固县| 国产女人18毛片水真多1| 成年女人喷潮免费视频| 性欧美老妇另类xxxx| 日本久久香蕉一本一道| 精品中文人妻在线不卡| 免费无码va一区二区三区| 日韩精品理论片一区二区| 欧美精品一区二区三区在线观看| 97久久久亚洲综合久久| 日韩熟女熟妇久久精品综合| 欧美人禽杂交狂配| 日本高清一区免费中文视频 | 少妇人妻偷人精品免费视频| 嫩草欧美曰韩国产大片| 国产一级特黄性生活大片| 啪啪av一区二区三区| 日韩av在线一区二区三区| 成人国产精品一区二区网站公司 | 麻豆亚州无矿码专区视频| 江永县| 亚洲国产av区一区二| 老妇肥熟凸凹丰满刺激| 精品在免费线中文字幕久久|