正解:并查集/树链剖分+线段树
解题报告:
感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ
首先说下并查集的方法趴QwQ
首先离线,读入所有操作,然后dfs遍历整棵树,如果当前点有标记就fa[i]=i,否则fa指向父亲节点
然后倒叙查答案,每次碰到Q答案就fa[i],碰到C就把修改的那个点的标记次数--,当标记次数=0的时候fa就指向父亲节点辣
over
484很妙昂!
#include<bits/stdc++.h> using namespace std; #define il inline #define gc getchar() #define t(i) edge[i].to #define w(i) edge[i].wei #define fy(i) edge[i].fy #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) #define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=100000+10; int n,q,ed_cnt,head[N],fa[N],fath[N],modi[N],as[N],as_cnt; struct ed{int to,nxt;}edge[N<<1]; struct node{char op;int x;}nod[N]; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch<'0' || ch>'9'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } int fd(ri x){return fa[x]==x?x:fa[x]=fd(fa[x]);} il char rd(){rc ch=gc;while(ch!='C' && ch!='Q')ch=gc;return ch;} il void ad(ri x,ri y){edge[++ed_cnt]=(ed){x,head[y]};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x]};head[x]=ed_cnt;} void dfs(ri x,ri fat){fath[x]=fat;if(!modi[x])fa[x]=fat;else fa[x]=x;e(i,x)if(t(i)^fat)dfs(t(i),x);} int main() { // freopen("4092.in","r",stdin);freopen("4092.out","w",stdout); n=read();q=read();rp(i,1,n-1){ri x=read(),y=read();ad(x,y);} rp(i,1,q){char ch;cin>>ch;nod[i]=(node){ch,read()};if(nod[i].op=='C')++modi[nod[i].x];}++modi[1]; dfs(1,0); my(i,q,1) { if(nod[i].op=='C'){--modi[nod[i].x];if(!modi[nod[i].x])fa[nod[i].x]=fa[fath[nod[i].x]];} else as[++as_cnt]=fd(nod[i].x); } my(i,as_cnt,1)printf("%d\n",as[i]); return 0; }
然后下面港下树剖+线段树
首先树剖基操不讲
然后考虑怎么维护打标记和查询操作
就直接在线段树上维护区间中的打标记的深度max
查询就直接在链上跳,找到深度max的那个节点,输出出来就好QwQ
啊表述得不太清晰的样子,,,等下放下代码再详细讲趴QAQ