不存在-1的情况,而且最多一轮就结束了。如果新增加的黑点v0会产生新的黑点v1,那么v0和v1肯定是在一条轴上的,而原来这条轴上已经有黑点了。
离散以后扫描线统计,往线段上插点,然后查询区间上点数。
不妨以x为主轴,用一条条平行于y轴的线去扫。
按照x为主y为副排序以后,记录下标,将下标按y为主排序,为的是把y相同的一系列点变成一个入点(d[id] = 1),一个出点(d[id] = -1),
可能某个相同y值的点只有一个,所以最后的出点 -= 1。
点可能有重复,判重的话就标记一下平行x轴的线。
/********************************************************* * ------------------ * * author AbyssalFish * **********************************************************/ #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<queue> #include<vector> #include<stack> #include<vector> #include<map> #include<set> #include<algorithm> #include<cmath> #include<numeric> using namespace std; const int maxn = 1e5; typedef long long ll; typedef pair<int,int> Point; #define xc first #define yc second Point p[maxn]; int ys[maxn], d[maxn]; //discrete y, scan line int n; int r[maxn]; bool cmp(int a,int b) { return p[a].yc < p[b].yc || (p[a].yc == p[b].yc && p[a].xc < p[b].xc); } int C[maxn+1], n0; bool vis[maxn+1]; int sum(int x) { int re = 0; while(x > 0){ re += C[x]; x &= x-1; } return re; } void add(int x,int d) { while(x <= n0){ C[x] += d; x += x&-x; } } void solve() { for(int i = 0; i < n; i++){ scanf("%d%d",&p[i].xc,&p[i].yc); r[i] = i; } //compress sort(p,p+n); sort(r,r+n,cmp); ys[r[0]] = 1; d[r[0]] = 1; for(int i = 1; i < n; i++){ ys[r[i]] = ys[r[i-1]]; if(p[r[i]].yc != p[r[i-1]].yc) { d[r[i-1]] -= 1; ys[r[i]]++; d[r[i]] = 1; } } n0 = ys[r[n-1]]; d[r[n-1]] -= 1; //memset(C+1,0,sizeof(int)*n0); ll ans = n; for(int i = 0, j; i < n;){ j = i; while(j < n && p[j].xc == p[i].xc) { //不包含端点 if(d[j] < 0) { vis[ys[j]] = false; add(ys[j], -1); } j++; } if(ys[i] < ys[j-1]-1) { ans += sum(ys[j-1]-1) - sum(ys[i]); for(int k = i+1; k < j-1; k++){ //去重 if(vis[ys[k]]) ans--; } } while(i < j) { if(d[i] > 0) { add(ys[i],1); vis[ys[i]] = true; } i++; } } printf("%I64d\n", ans); } //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif scanf("%d", &n); solve(); return 0; }
时间: 2024-10-11 22:48:32