PTA L3-026 传送门 (splay) (2020团体程序设计天梯赛)

题目链接

快住手,这不是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\n",ans);
54     }
55     return 0;
56 }

场上暴力水了十几分,菜菜菜

posted @ 2020-12-15 17:06  jrltx  阅读(629)  评论(0编辑  收藏  举报