POJ - 3109 Inner Vertices

不存在-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;
}

 

转载于:https://www.cnblogs.com/jerryRey/p/4977454.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值