考虑这样的操作连出一颗森林
于是先离线建出树来
修改就是子树操作
只需要对于每个询问找到该点上一个被覆成
0
0
0的时间
然后对时间区间询问即可
复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
写的有点长,似乎有 2 k 2k 2k不到写完的(
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline ll readll(){
char ch=gc();
ll res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=1000005;
namespace Seg{
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
int tag[N<<2];
inline void pushdown(int u){
if(!tag[u])return ;
tag[lc]=tag[u],tag[rc]=tag[u];
tag[u]=0;
}
void update(int u,int l,int r,int st,int des,int k){
if(st<=l&&r<=des){tag[u]=k;return;}
pushdown(u);
if(st<=mid)update(lc,l,mid,st,des,k);
if(mid<des)update(rc,mid+1,r,st,des,k);
}
int query(int u,int l,int r,int p){
if(l==r)return tag[u];
pushdown(u);
if(p<=mid)return query(lc,l,mid,p);
else return query(rc,mid+1,r,p);
}
#undef lc
#undef rc
#undef mid
}
int n,q,m,qn;
namespace Bit{
ll tr[N];
#define lb(x) (x&(-x))
void update(int p,ll k){
//cout<<"U "<<p<<'\n';
for(;p<=m;p+=lb(p))tr[p]+=k;
//cout<<"EDN\n";
}
inline ll qry(int p,ll res=0){
// cout<<"Q "<<p<<'\n';
for(;p>0;p-=lb(p))res+=tr[p];
// cout<<"Ed\n";
return res;
}
ll query(int l,int r){return qry(r)-qry(l-1);}
#undef lb
}
ll ans[N];
vector<int> upd[N];
vector<pair<pii,int>> qr[N];
struct tree{
int lc[N],rc[N];
int in[N],out[N],siz[N],dfn,ff[N],tot;
int kd;
inline int find(int x){
return ff[x]==x?x:ff[x]=find(ff[x]);
}
inline void merge(int u,int v){
int f1=find(u),f2=find(v);
if(f1==f2)return;
++tot,ff[f1]=ff[f2]=ff[tot]=tot;
lc[tot]=f1,rc[tot]=f2;
}
inline void init(){tot=n;
for(int i=1;i<=n;i++)ff[i]=i;
}
void dfs(int u){
in[u]=++dfn;siz[u]=(u<=n);
if(lc[u])dfs(lc[u]),siz[u]+=siz[lc[u]];
if(rc[u])dfs(rc[u]),siz[u]+=siz[rc[u]];
out[u]=dfn;
}
void build(){
for(int i=1;i<=tot;i++)if(ff[i]==i)dfs(i);
}
void update(int u,int i){
Seg::update(1,1,tot,in[u],out[u],i);
}
int query(int u){
return Seg::query(1,1,tot,in[u]);
}
void dfs2(int u){
for(int &x:upd[u])
Bit::update(x,siz[u]);
for(pair<pii,int> &x:qr[u])
ans[x.se]=Bit::query(x.fi.fi,x.fi.se);
if(lc[u])dfs2(lc[u]);
if(rc[u])dfs2(rc[u]);
for(int &x:upd[u])
Bit::update(x,-siz[u]);
}
void solve(){
for(int i=1;i<=tot;i++)if(ff[i]==i)dfs2(i);
}
}t1,t2;
struct opt{
int op,x;
opt(int a=0,int b=0):op(a),x(b){}
}p[N];
char str[3];
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read(),q=read();
t1.init(),t2.init();
for(int i=1,x,y;i<=q;i++){
readstring(str);
switch(str[1]){
case 'U':x=read(),y=read(),t1.merge(x,y);break;
case 'M':x=read(),y=read(),t2.merge(x,y);break;
case 'A':x=read(),p[++m]=opt(1,t1.find(x));break;
case 'Z':x=read(),p[++m]=opt(2,t2.find(x));break;
case 'Q':x=read(),p[++m]=opt(3,x);break;
}
}
t1.build(),t2.build();
for(int i=1;i<=m;i++){
switch(p[i].op){
case 1:upd[p[i].x].pb(i);;break;
case 2:t2.update(p[i].x,i);break;
case 3:qr[p[i].x].pb(make_pair(pii(t2.query(p[i].x),i),++qn));break;
}
}
t1.solve();
for(int i=1;i<=qn;i++)cout<<ans[i]<<'\n';
return 0;
}