题目:有 n 个点,一个点集 S 是好的,当且仅当对于他的每个子集 T,存在一个右边无限长的矩形,使得这个矩形包含了 T,但是和 S-T 没有交求这 n 个点里有几个好的点集 1<=n<=10^5
思路:对于 |S|=1,他显然是好的
对于 |S|=2,只要两个点的 y 坐标不相同,那么这个集合也是好的
对于 |S|=3,三个点的形状必须是 < 型。用树状数组统计,按x从大到小排序,对于一个点,ans+=小于他y坐标的点数*大他要y坐标的点数。
对于 |S|>3,不可能任何三个点都是 < 型,所以一定不是好的。
能读懂题意就好了。。。
取模不是1e9+7啊,
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll mod=998244353ll;//取模不是1e9+7!!!
struct node{
int x,y;
}a[maxn];
int n,tot,b[maxn];
bool cmp(const node &a,const node &b)
{
return a.x>b.x;
}
int c[maxn];
int lowbit(int x){return x&-x;}
void update(int pos,int val)
{
while(pos<=n)
{
c[pos]+=val;
pos+=lowbit(pos);
}
}
int query(int pos)
{
int ans=0;
while(pos>0)
{
ans+=c[pos];
pos-=lowbit(pos);
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
b[i]=a[i].y;
}
sort(b+1,b+n+1);
ll ans=0;
ans+=1ll*n;//1
(ans+=1ll*(n-1)*n/2)%=mod;//2
int num=0;
for(int i=1;i<=n;i++)
{
if(b[i]!=b[i-1])
num=0;
else num++;
ans=(ans-1ll*num+mod)%mod;
}
tot=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)
a[i].y=lower_bound(b+1,b+tot+1,a[i].y)-b;
sort(a+1,a+n+1,cmp);
int last=1;
for(int i=1;i<=n;i++)
{
if(a[i].x!=a[i-1].x)
{
for(int j=last;j<i;j++)//一个x坐标可能有多个y坐标相同的,需要放在一起更新
update(a[j].y,1);
last=i;
}
int s1=query(a[i].y-1);
int s2=query(n)-query(a[i].y);
ans=(ans+1ll*s1*s2)%mod;
}
printf("%lld\n",ans);
return 0;
}