#include<bits/stdc++.h>
#define il inline
#define ui unsigned int
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define ldb long double
#define pii pair<int,int>
#define vi vector<int>
#define vpii vector<pii>
#define fir first
#define sec second
#define gc getchar
#define pc putchar
#define mst(a,x) memset(a,x,sizeof a)
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define pct __builtin_popcount
using namespace std;
const int N=2e5+10,INF=0x3f3f3f3f,MOD=1e9+7,dx[]={-1,-1,0,1},dy[]={0,1,1,1};
const ll INFll=0x3f3f3f3f3f3f3f3f;
il int rd() {int x=0,f=1; char ch=gc(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f;}
il ll rdll() {ll x=0; int f=1; char ch=gc(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f;}
il void wr(int x) {if(x<-2147483647) {printf("-2147483648"); return;} if(x<0) {pc('-'),wr(-x); return;} if(x<10) {pc(x+'0'); return;} wr(x/10),pc(x%10+'0');}
il void wrll(ll x) {if(x<-9223372036854775807) return (void)printf("-9223372036854775808"); if(x<0) return pc('-'),wrll(-x); if(x<10) return (void)pc(x+'0'); wrll(x/10),pc(x%10+'0');}
il void wr(int x,char *s) {wr(x),printf("%s",s);}
il void wrll(ll x,char *s) {wrll(x),printf("%s",s);}
il int vmod(int x) {return x>=MOD?x-MOD:x;}
il int vadd(int x,int y) {return vmod(x+y);}
il int vsub(int x,int y) {return vmod(x-y+MOD);}
il int vmul(int x,int y) {return 1ll*x*y%MOD;}
int n,cnt,X[N],Y[N],b[N]; ll ans; set<pii> S; map<pii,int> M; vi V[N],T[N];
struct GP { // find every E-DCC
int id=1,idx,cnt,to[N<<3],ne[N<<3],head[N],col[N],dfn[N],low[N],f[N<<3];
void add(int x,int y) {to[++id]=y,ne[id]=head[x],head[x]=id;}
void dfs1(int u,int pre) {
dfn[u]=low[u]=++idx;
for(int i=head[u];i;i=ne[i]) {
int v=to[i];if(i==(pre^1)) continue;
if(!dfn[v]) {dfs1(v,i),low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) f[i]=f[i^1]=1;}
else if(low[u]>=dfn[v]) low[u]=min(low[u],dfn[v]);
}
}
void dfs2(int u) {col[u]=cnt,V[cnt].pb(u); for(int i=head[u],v;i;i=ne[i]) if(!f[i]&&!col[v=to[i]]) dfs2(v);}
} G;
void QwQ() {
n=rd(); for(int i=1;i<=n;i++) X[i]=rd()+1,Y[i]=rd()+1,S.insert({X[i],Y[i]}),M[{X[i],Y[i]}]=i;
for(int i=1,nx,ny;i<=n;i++) for(int j=0;j<4;j++) {nx=X[i]+dx[j],ny=Y[i]+dy[j]; if(S.count({nx,ny})) G.add(i,M[{nx,ny}]),G.add(M[{nx,ny}],i);}
for(int i=1;i<=n;i++) if(!G.dfn[i]) G.dfs1(i,0);
for(int i=1;i<=n;i++) if(!G.col[i]) G.cnt++,G.dfs2(i);
for(int i=1;i<=G.cnt;i++) {
int mn=INF,mx=0,bg=INF,ed=0; for(int j:V[i]) T[X[j]].pb(Y[j]),bg=min(bg,Y[j]),ed=max(ed,Y[j]),mn=min(mn,X[j]),mx=max(mx,X[j]);
sort(T[mn].begin(),T[mn].end()),S.clear();
b[bg-1]=b[ed+1]=0; for(int j=bg;j<=ed;j++) b[j]=1; for(int j:T[mn]) b[j]=0,cnt++; ans+=cnt;
for(int j=bg,p;j<=ed+1;j++) if(b[j]&&!b[j-1]) p=i; else if(!b[j]&&b[j-1]) S.insert({p,j-1});
for(int j=mn+1;j<=mx;j++) {
sort(T[j].begin(),T[j].end());
for(int k:T[j]) { // block
auto it=prev(S.ub({k+1,k+1})); int f=it->fir,s=it->sec;
if(f<=k&&k<=s) {
S.erase(it);
if(f<k) S.insert({f,k-1}); if(k<s) S.insert({k+1,s});
}
}
set<pii> tmp;
for(pii P:S) { // spread
int f=P.fir,s=P.sec,F,S; auto l=lb(T[j].begin(),T[j].end(),f),r=ub(T[j].begin(),T[j].end(),s);
if(l!=T[j].begin()) f=*prev(l); if(r!=T[j].end()) s=*r; tmp.insert({f,s});
}
S=tmp; int len=ed-bg+1; for(pii P:S) len-=P.sec-P.fir+1; ans+=len;
}
for(int j:V[i]) T[X[j]].clear();
}
wrll(ans-n,"\n");
}
signed main() {
int T=1; while(T--) QwQ();
}
思路:先跑边双,对每个边双连通分量分别求答案。
求答案时按x坐标扫描线,像珂朵莉树一样用set维护“漏风”的区间。
目前样例1输出-3,不知道思路对不对。