- RT,这是 lz P5214 的代码,实现的是线段树分治。想问明明把空间都加了整体 5 但是
mxQ
开成 104 就炸了开成 104+1 就能过啊 QwQ 可能我比较蠢是什么细节的问题吧
#include<bits/stdc++.h>
#define inl inline
using namespace std;
const int mxN(5e3),mxM(2e5),mxQ((1e4)+1);
int n,m,q,Ans[mxQ+5];
vector<int>asktm;
struct Edge{int u,v;};
inl bool operator <(Edge a,Edge b){return ((a.u==b.u)?(a.v<b.v):(a.u<b.u));}
//1.重载运算符要写在namespace外面;
//2.std::map默认用'<'运算符比较key,但map<int,vector<int> >没有重载这个运算符,
//所以要实现一个operator'<',或者在第3个模板参数里传入比较器.
namespace Dsu{//以tp为依据:记住没有mrg就没有多余的cancel.
int an[mxN+5],siz[mxN+5];
int tp;struct P{int u,v,lnks;}st[mxM+mxQ+5];
inl void init(){
tp=0,st[tp].lnks=n;//初始化联通块个数.
for(int u(1);u<=n;++u)an[u]=u,siz[u]=1;
}
inl int Getan(int u){while(an[u]!=u)u=an[u];return u;}
inl void mrg(int u,int v){
u=Getan(u),v=Getan(v);
if(u==v)return;//联通块个数不变.
if(siz[u]>siz[v])swap(u,v);//siz(u)<siz(v).
int lstlnks(st[tp].lnks);
st[++tp]=(P){u,v,lstlnks-1};
siz[v]+=siz[u],an[u]=v;
}
inl void cancel(){
P top(st[tp--]);
an[top.u]=top.u,siz[top.v]-=siz[top.u];
}
}
namespace Sgt{
#define mid (l+r>>1)
#define o ID(l,r)
#define ls ID(l,mid)
#define rs ID(mid+1,r)
vector<Edge>e[(mxQ<<1)+5];
inl int ID(int l,int r){return l+r|l!=r;}
inl void upd(int l,int r,int ql,int qr,Edge E){
if(ql<=l&&r<=qr){e[o].push_back(E);return;}
if(ql<=mid)upd(l,mid,ql,qr,E);
if(qr>mid)upd(mid+1,r,ql,qr,E);
}
inl void upd(int l,int r,Edge E){if(l<=r)upd(0,mxQ,l,r,E);}
inl void sol(int l,int r){
using namespace Dsu;
int lsttp(tp);
for(int i(0);i<e[o].size();++i)mrg(e[o][i].u,e[o][i].v);
if(l==r)Ans[l]=st[tp].lnks;else sol(l,mid),sol(mid+1,r);
while(tp!=lsttp)cancel();
}
}
namespace G{
map<Edge,vector<int> >occtm;//tm是关键字.
//最开始就有的边出现的时间设为0.
//E这条边在操作序列里出现的时间顺序是occtm[E][].
inl void add(Edge e,int t){
if(e.u>e.v)swap(e.u,e.v);//注意这样才能保证一条边的唯一性.
occtm[e].push_back(t);
}
inl void init(){
for(map<Edge,vector<int> >::iterator it(occtm.begin());it!=occtm.end();++it){
Edge e(it->first);
for(int i(0);i<occtm[e].size();i+=2){
int l(occtm[e][i]),r;
if(i+1<occtm[e].size())r=occtm[e][i+1];else r=mxQ;
Sgt::upd(l,r-1,e);
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i(1),u,v;i<=m;++i)scanf("%d%d",&u,&v),G::add((Edge){u,v},0);
scanf("%d",&q);
for(int Q(1),u,v;Q<=q;++Q){
string op;cin>>op;
if(op[0]=='Q')asktm.push_back(Q);
else scanf("%d%d",&u,&v),G::add((Edge){u,v},Q);
}
G::init(),Dsu::init(),Sgt::sol(0,mxQ);
for(int i(0);i<asktm.size();++i)printf("%d\n",Ans[asktm[i]]);
return 0;
}