Tokitsukaze and Strange Rectangle CodeForces - 1191F (树状数组,计数)

大意: 给定$n$个平面点, 定义集合$S(l,r,a)$表示横坐标$[l,r]$纵坐标$[a,\infty]$内的所有点. 求可以得到多少种不同的集合.

从上往下枚举底层最右侧点, 树状数组统计贡献.

#include <iostream>
#include <algorithm>
#include <cstdio>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;
const int N = 1e6+10, INF = 0x3f3f3f3f;
int n, c[N], vis[N], b[N];
struct _ {
	int x,y;
	bool operator < (const _&rhs) const {
		if (y!=rhs.y) return y>rhs.y;
		return x<rhs.x;
	}
} a[N];
int ID(int x) {
	return lower_bound(b+1,b+1+*b,x)-b;
}
int qry(int x) {
	int r = 0;
	for (; x; x^=x&-x) r+=c[x];
	return r;
}
int qry(int l, int r) {
	return qry(ID(r))-qry(ID(l-1));
}
void add(int x) {
	x = ID(x);
	if (!vis[x]) {
		vis[x] = 1;
		for (; x<=*b; x+=x&-x) ++c[x];
	}
}
int main() {
	scanf("%d", &n);
	REP(i,1,n) { 
		scanf("%d%d",&a[i].x,&a[i].y);
		b[++*b]=a[i].x;
		b[++*b]=a[i].x-1;
	}
	b[++*b]=0,b[++*b]=INF;
	sort(b+1,b+1+*b),*b=unique(b+1,b+1+*b)-b-1;
	sort(a+1,a+1+n);
	ll ans = 0;
	REP(i,1,n) {
		int j=i;
		while (j<n&&a[j+1].y==a[i].y) ++j;
		REP(k,i,j) { 
			int L = qry(1,a[k].x-1);
			int R = qry(a[k].x+1,k==j?INF:a[k+1].x-1);
			ans += (ll)(L+1)*(R+1);
			add(a[k].x);
		}
		i = j;
	}
	printf("%lld\n", ans);
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/11183907.html