题目链接
http://codeforces.com/contest/1191/problem/F
题意
给你n个点,用一个开口向上的矩形包围一些点,问有多少种不同的情况
题解:
树状数组
将x,y坐标分别排序
从上到下计算,利用树状数组维护
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200005;
int c[maxn],n;
int a[maxn],b[maxn];
vector<int>v[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int v)
{
while(x<=n)
{
c[x]+=v;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void compress(vector<int>&vec)
{
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
}
int main()
{
memset(c,0,sizeof(c));
cin>>n;
vector<int>vx,vy;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i],&b[i]);
vx.push_back(a[i]);
vy.push_back(b[i]);
}
compress(vx);
compress(vy);
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(vx.begin(),vx.end(),a[i])-vx.begin()+1;
b[i]=lower_bound(vy.begin(),vy.end(),b[i])-vy.begin()+1;
v[b[i]].push_back(a[i]);
}
long long ans=0;
for(int i=n;i>=1;i--)
{
sort(v[i].begin(),v[i].end());
for(int j=0;j<v[i].size();j++)
{
int t=v[i][j];
if( sum(t)-sum(t-1))continue;
add(t,1);
}
int pre=0;
for(int j=0;j<v[i].size();j++)
{
int t=v[i][j];
ans+=1ll*(sum(t)-sum(pre))*(sum(n)-sum(t-1));
pre=t;
}
}
cout<<ans<<endl;
}