快住手,这不是ACM!!!
将所有需要添加或者删除的传送门的y值离散化,一开始初始化成n条链,传送门对应链上的结点。对于每个操作,实际上要做的是“分别查询两个结点各自所在链上的左右端点”和“将两个结点的后继结点交换”,用splay可以做到$O(log(q))$时间修改和查询。添加和删除传送门的操作其实是等价的,因此前面的"+"和"-"可以无视
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 const int N=5e5+10,inf=0x3f3f3f3f; 6 int n,m,fa[N],ch[N][2],tot,X[N]; 7 ll ans; 8 #define l(u) ch[u][0] 9 #define r(u) ch[u][1] 10 int sf(int u) {return u==r(fa[u]);} 11 bool isrt(int u) {return u!=l(fa[u])&&u!=r(fa[u]);} 12 void rot(int u) { 13 int v=fa[u],f=sf(u); 14 if(!isrt(v))ch[fa[v]][sf(v)]=u; 15 ch[v][f]=ch[u][f^1],fa[ch[v][f]]=v; 16 fa[u]=fa[v],ch[u][f^1]=v,fa[v]=u; 17 } 18 int newnode() {int u=++tot; fa[u]=l(u)=r(u)=0; return u;} 19 void splay(int u) {for(; !isrt(u); rot(u))if(!isrt(fa[u])&&sf(fa[u])==sf(u))rot(fa[u]);} 20 int fdl(int u) {splay(u); for(; l(u); u=l(u)); splay(u); return u;} 21 int fdr(int u) {splay(u); for(; r(u); u=r(u)); splay(u); return u;} 22 struct QR {int x1,x2,y1,y2;} qr[N]; 23 vector<int> rt[N]; 24 25 int main() { 26 scanf("%d%d",&n,&m); 27 for(int i=1; i<=m; ++i)scanf(" %*c%d%d%d",&qr[i].x1,&qr[i].x2,&qr[i].y1); 28 for(int i=1; i<=n; ++i)rt[i].push_back(0),rt[i].push_back(inf); 29 for(int i=1; i<=m; ++i)rt[qr[i].x1].push_back(qr[i].y1),rt[qr[i].x2].push_back(qr[i].y1); 30 for(int i=1; i<=n; ++i) { 31 sort(rt[i].begin(),rt[i].end()); 32 rt[i].resize(unique(rt[i].begin(),rt[i].end())-rt[i].begin()); 33 } 34 for(int i=1; i<=m; ++i) { 35 int y=qr[i].y1; 36 qr[i].y1=lower_bound(rt[qr[i].x1].begin(),rt[qr[i].x1].end(),y)-rt[qr[i].x1].begin(); 37 qr[i].y2=lower_bound(rt[qr[i].x2].begin(),rt[qr[i].x2].end(),y)-rt[qr[i].x2].begin(); 38 } 39 for(int i=1; i<=n; ++i) { 40 for(int j=0; j<rt[i].size(); ++j)rt[i][j]=newnode(),X[rt[i][j]]=i; 41 for(int j=0; j<rt[i].size()-1; ++j)r(rt[i][j])=rt[i][j+1],fa[rt[i][j+1]]=rt[i][j]; 42 } 43 ans=(ll)n*(n+1)*(2*n+1)/6; 44 for(int i=1; i<=m; ++i) { 45 int x1=qr[i].x1,x2=qr[i].x2,y1=qr[i].y1,y2=qr[i].y2; 46 int u=rt[x1][y1],v=rt[x2][y2]; 47 int lu=X[fdl(u)],ru=X[fdr(u)],lv=X[fdl(v)],rv=X[fdr(v)]; 48 ans-=(ll)lu*ru+(ll)lv*rv; 49 ans+=(ll)lu*rv+(ll)lv*ru; 50 splay(u),splay(v); 51 int u2=r(u),v2=r(v); 52 r(u)=v2,r(v)=u2,fa[v2]=u,fa[u2]=v; 53 printf("%lld ",ans); 54 } 55 return 0; 56 }
场上暴力水了十几分,菜菜菜