제출 #653166

#제출 시각아이디문제언어결과실행 시간메모리
653166inksamuraiInside information (BOI21_servers)C++17
100 / 100
534 ms65092 KiB
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define rng(i,c,n) for(int i=c;i<n;i++)
#define fi first
#define se second
#define pb push_back
#define sz(a) (int)a.size()
#define vec(...) vector<__VA_ARGS__>
#define _3D2ZDxo ios::sync_with_stdio(0),cin.tie(0)
typedef long long ll;
using pii=pair<int,int>;
using vi=vector<int>;
void print(){cout<<'\n';}
template<class h,class...t>
void print(const h&v,const t&...u){cout<<v<<' ',print(u...);}

#define all(a) a.begin(),a.end()

template<class E>
struct treelca{
	int n;
	int timer=0;
	vec(vec(E)) adj;
	vi tin,tout,tour,tourid;
	vi segtree;
	vi depth;
	treelca(int m,int root,vec(vec(E)) neadj){
		init(m,root,neadj);
	}
	void init(int m,int root,vec(vec(E)) neadj){
		n=m;
		tin.clear();
		tout.clear();
		tour.clear();
		tourid.clear();
		depth.clear();
		tin.resize(n,0);
		tout.resize(n,0);
		tourid.resize(n,0);
		depth.resize(n,0);
		adj=neadj;
		dfs(root,-1);
		segtree.resize(4*sz(tour));
		build(1,0,sz(tour)-1);
	}
	void dfs(int v,int par){
		tour.pb(v);
		tourid[v]=sz(tour)-1;
		tin[v]=timer++;
		for(auto e:adj[v]){
			int u=e.to;
			if(u==par) continue;
			depth[u]=depth[v]+1;
			dfs(u,v);
			tour.pb(v);
		}
		tout[v]=timer++;
	}
	void build(int node,int l,int r){
		if(l==r){
			segtree[node]=tour[l];
		}else{
			int m=(l+r)>>1;
			build(node*2,l,m);
			build(node*2+1,m+1,r);
			segtree[node]=(tin[segtree[node*2]]<tin[segtree[node*2+1]]?segtree[node*2]:segtree[node*2+1]);
		}
	}
	int query(int node,int l,int r,int _l,int _r){
		if(l>_r or r<_l) return -1;
		if(l>=_l and r<=_r) return segtree[node];
		int m=(l+r)>>1;
		int vl=query(node*2,l,m,_l,_r);
		int vr=query(node*2+1,m+1,r,_l,_r);
		if(min(vl,vr)==-1) return max(vl,vr);
		return (tin[vl]<tin[vr]?vl:vr);
	}
	int ancestor(int from,int to){
		int tinfrom=tin[from],tinto=tin[to];
		if(tinfrom>tinto) swap(tinfrom,tinto);
		return query(1,0,sz(tour)-1,tinfrom,tinto);
	}
	int dist(int u,int v){
		return depth[u]+depth[v]-depth[ancestor(u,v)]*2;
	}
};

struct fenwick{
	int n;
	vector <int> bit;
	fenwick(int m){
		init(m);
	}
	void init(int m){
		n=m;
		bit.resize(n,0);
	}
	int get(int i){
		int s=0;
		while(i){
			s+=bit[i];
			i-=i&-i;
		}
		return s;
	}
	void add(int i,int x){
		while(i<=n){
			bit[i]+=x;
			i+=i&-i;
		}
	}
};

struct E{
	int to,w;
	E(int _to=0,int _w=0):
	to(_to),w(_w){}
	bool operator<(const E&a)const{
		return pii(w,to)<pii(a.w,to);
	}
};

const int inf=1e9;

signed main(){
_3D2ZDxo;
	int n,q;
	cin>>n>>q;
	q+=n-1;
	vec(vec(E)) adj(n);
	vec(vi) qry1(n);
	vec(vec(pii)) qry(n);
	vi pns(q,-1);
	vi reb(q,0);
	rep(i,q){
		char ch;
		cin>>ch;
		if(ch=='S'){
			int u,v;
			cin>>u>>v;
			u-=1,v-=1;
			adj[u].pb(E(v,i));
			adj[v].pb(E(u,i));
		}else if(ch=='Q'){
			int u,v;
			cin>>u>>v;
			u-=1,v-=1;
			reb[i]=1;
			qry[v].pb({u,i});
		}else{
			int v;
			cin>>v;
			v-=1;
			pns[i]=0;
			qry1[v].pb(i);
		}
	}
	// answering first query
	{
		vi leb(n); // last node where increasing seq broke
		vi bel(n); // last node where decreasing seq broke
		vi par(n);
		vi par_wit(n);
		auto dfs=[&](auto self,int v,int _lst)->void{
			for(auto [u,w]:adj[v]){
				if(u==par[v]) continue;
				if(_lst>=w){
					leb[u]=v;
				}else{
					leb[u]=leb[v];
				}
				if(_lst<=w){
					bel[u]=v;
				}else{
					bel[u]=bel[v];
				}
				par[u]=v;
				par_wit[u]=w;
				self(self,u,w);
			}
		};
		dfs(dfs,0,0);
		vec(vi) afup(20,vi(n)); // affine up
		afup[0]=par;
		rng(j,1,20){
			rep(v,n){
				int up=afup[j-1][v];
				afup[j][v]=afup[j-1][up];
			}
		}
		treelca<E> lca(n,0,adj);
		auto move_down=[&](int v,int up)->int{
			int dist=lca.dist(v,up)-1;
			per(j,20){
				if(dist>>j&1){
					v=afup[j][v];
				}
			}
			return v;
		};
		rep(v,n){
			for(auto p:qry[v]){
				int u=p.fi;
				int j=p.se;
				bool pok=0;
				if(u==v){
					pok=1;
				}else{
					int up=lca.ancestor(u,v);
					if(up==v){
						if(lca.depth[leb[u]]<=lca.depth[up]){
							pok=par_wit[u]<=j;
						}
					}else if(up==u){
						if(lca.depth[bel[v]]<=lca.depth[up]){
							pok=par_wit[move_down(v,u)]<=j;
						}
					}else{
						if(lca.depth[leb[u]]<=lca.depth[up] and lca.depth[bel[v]]<=lca.depth[up]){
							int lov=move_down(v,up);
							int lou=move_down(u,up);
							pok=par_wit[lov]<=par_wit[lou] and par_wit[u]<=j;
						}
					}
				}
				pns[j]=pok;
			}
		}
	}
	// answering second query
	{
		rep(v,n){
			sort(all(adj[v]));
		}
		int num=0;
		vi usd(n);
		vi chs(n);
		auto refill=[&](auto self,int v,int par)->void{
			num+=1;
			chs[v]=1;
			for(auto [to,w]:adj[v]){
				if(to==par or usd[to]) continue;
				self(self,to,v);
				chs[v]+=chs[to];
			}
		};
		auto find_centroid=[&](auto self,int v,int par)->int{
			for(auto [to,w]:adj[v]){
				if(to==par or usd[to]) continue;
				if(chs[to]*2>num){
					return self(self,to,v);
				}
			}
			return v;
		};
		fenwick bit(q+1);
		auto ask=[&](auto self,int v,int par,int _lst,int __lst)->void{
			for(auto j:qry1[v]){
				pns[j]+=bit.get(j+1)+(j>=__lst);
				// print(pns[j],j,bit.get(j+1));
			}
			for(auto [to,w]:adj[v]){
				if(to==par or usd[to]) continue;
				if(w>_lst) continue;
				self(self,to,v,w,__lst);
			}
		};
		auto add=[&](auto self,int v,int par,int _lst,int x)->void{
			bit.add(_lst+1,x);
			// print(v,_lst+1);
			for(auto [to,w]:adj[v]){
				if(to==par or usd[to]) continue;
				if(w<_lst) continue;
				self(self,to,v,w,x); 
			}
		};
		auto dfs=[&](auto self,int v,int par)->void{
			num=0;
			refill(refill,v,par);
			int rt=find_centroid(find_centroid,v,par);
			usd[rt]=1;
			per(i,sz(adj[rt])){
				auto [to,w]=adj[rt][i];
				if(to==par or usd[to]) continue;
				ask(ask,to,rt,w,w);
				add(add,to,rt,w,1);
			}
			for(auto j:qry1[rt]){
				pns[j]+=bit.get(j+1);
			}
			per(i,sz(adj[rt])){
				auto [to,w]=adj[rt][i];
				if(to==par or usd[to]) continue;
				add(add,to,rt,w,-1);	
			}
			rep(i,sz(adj[rt])){
				auto [to,w]=adj[rt][i];
				if(to==par or usd[to]) continue;
				self(self,to,rt);
			}
		};
		dfs(dfs,0,-1);
	}
	rep(i,q){
		if(pns[i]==-1) continue;
		if(reb[i]){
			cout<<(pns[i]?"yes":"no")<<"\n";
		}else{
			cout<<pns[i]+1<<"\n";
		}
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...