cf573 1d Tokitsukaze and Strange Rectangle

题意:给定平面上的一些坐标点,现在用U形区域\(l<=y<=r, x>=h\)框出这些点的子集,问这样的子集有多少个。

比较显然的扫描线计数的题。拿个树状数组维护左区间有多少个点,一行扫过去统计就行了。点出现同一行的情况会麻烦点,但也不难处理。

  1.     #include <iostream>
  2.     #include <cstdio>
  3.     #include <cmath>
  4.     #include <cstring>
  5.     #include <algorithm>
  6.     using namespace std;
  7.     const int maxn=200010;
  8.     typedef long long ll;
  9.     struct Node{
  10.     	int x,y;
  11.     	bool operator<(const Node &v){
  12.     		if (y==v.y) return x<v.x;
  13.     		return y>v.y;
  14.     	}
  15.     }p[maxn];
  16.  
  17.     int dr[maxn];
  18.  
  19.     int tr[maxn];
  20.     void add(int p, int x){for(;p<maxn;p+=p&-p)tr[p]+=x;}
  21.     ll sum(int p){ll ret=0;for(;p;p-=p&-p)ret+=tr[p];return ret;}
  22.  
  23.     bool used[maxn];
  24.  
  25.     int main(){
  26.     	int n; cin>>n;
  27.     	for (int i=0;i<n;i++){
  28.     		int x,y;
  29.     		scanf("%d%d",&x,&y);
  30.     		p[i]=(Node){x,y};
  31.     		dr[i]=x;
  32.     	}
  33.     	sort(dr,dr+n);
  34.     	sort(p,p+n);
  35.     	int n1=unique(dr,dr+n)-dr;
  36.     	for (int i=0;i<n;i++) p[i].x=lower_bound(dr,dr+n1,p[i].x)-dr+1;
  37.     	ll ans=0;
  38.     	for (int i=0;i<n;){
  39.     		int r=i;
  40.     		while (r<n && p[r+1].y==p[r].y) r++;
  41.     		int u;
  42.     		for (int j=i;j<=r;j++){
  43.     			u=p[j].x;
  44.     			if (!used[u]){
  45.     				used[u]=1;
  46.     				add(u,1);
  47.     			}
  48.     		}
  49.     		u=maxn-1;
  50.     		for (int j=r;j>=i;j--){
  51.     			ans+=(sum(u-1)-sum(p[j].x)+1)*(sum(p[j].x-1)+1);
  52.     			u=p[j].x;
  53.     		}
  54.     		i=r+1;
  55.     	}
  56.     	cout<<ans<<'\n';
  57.     	return 0;
  58.     }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注