线段树+标记永久化。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 100500 #define maxe 200500 using namespace std; int n,q,x,y,nume=0,g[maxv],w[maxv],hash[maxv],tot=0,cnt=0,mx[maxv]; int ls[maxv<<2],rs[maxv<<2],lazy[maxv<<2],root; char type[10]; bool vis[maxv]; struct edge { int v,nxt; }e[maxe]; void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void dfs(int now) { w[now]=++cnt;hash[cnt]=now;mx[now]=w[now]; for (int i=g[now];i;i=e[i].nxt) { int v=e[i].v; dfs(v); mx[now]=max(mx[now],mx[v]); } } void build(int &now,int left,int right) { now=++tot;lazy[now]=0; if (left==right) return; int mid=(left+right)>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); } void modify(int now,int left,int right,int l,int r,int p) { if ((left==l) && (right==r)) { lazy[now]=max(lazy[now],p); return; } int mid=(left+right)>>1; if (r<=mid) modify(ls[now],left,mid,l,r,p); else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,p); else { modify(ls[now],left,mid,l,mid,p); modify(rs[now],mid+1,right,mid+1,r,p); } } int query(int now,int left,int right,int p) { if ((left==right) && (left==p)) return max(1,lazy[now]); int mid=(left+right)>>1,regis=0; if (p<=mid) regis=query(ls[now],left,mid,p); else regis=query(rs[now],mid+1,right,p); return max(regis,lazy[now]); } int main() { scanf("%d%d",&n,&q);vis[1]=true; for (int i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); addedge(x,y); } dfs(1); build(root,1,cnt); for (int i=1;i<=q;i++) { scanf("%s",type); if (type[0]==‘Q‘) { scanf("%d",&x); printf("%d\n",hash[query(root,1,cnt,w[x])]); } else { scanf("%d",&x); if (!vis[x]) { vis[x]=true; modify(root,1,cnt,w[x],mx[x],w[x]); } } } return 0; }
时间: 2024-10-06 01:27:10