CF1190D Tokitsukaze and Strange Rectangle 题解

Codeforces
Luogu

Description.

给定平面上 \(n(n\le 10^5)\) 个点,问有几种不同的选点方案,使得它能被一个没有上边界的矩形所包含,且其他没有点被这个矩形包含。

Solution.

数数数重了。

首先,我们发现有一个很显然的做法,就是从上往下考虑。
每次把当前这个 \(y\) 坐标的加入后统计答案。
然后刚开始以为这个答案就是 \(\frac{n\times (n+1)}2\),然后发现太 Naive 了。
因为当前这层如果完全不选,答案就在上一层和这一层重复统计了。
所以我们只能考虑对每个数统计答案。
插入一个数后我们需要考虑它可以有多少贡献。
在同一层中,我们强制钦定一个点选且它后面那个点不选,然后相当于统计前面和到下一个点数乘积。
然后直接树状树组维护即可。

Coding.

点击查看ex代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}/*}}}*/
int n,xt,yt,X[200005],Y[200005],tn[200005],ut,T[200005];
char vs[200005];vector<int>v[200005];ll rs=0;
inline void add(int x,int w) {for(;x<=xt;x+=x&(-x)) T[x]+=w;}
inline int qry(int x) {int r=0;for(;x;x-=x&(-x)) r+=T[x];return r;}
inline int q(int l,int r) {return qry(r)-qry(l-1);}
int main()
{
	read(n);for(int i=1;i<=n;i++) read(X[i]),read(Y[i]);
	tn[ut=1]=0;for(int i=1;i<=n;i++) tn[++ut]=X[i];
	sort(tn+1,tn+ut+1),xt=ut=unique(tn+1,tn+ut+1)-tn-1;
	for(int i=1;i<=n;i++) X[i]=lower_bound(tn+1,tn+ut+1,X[i])-tn;
	tn[ut=1]=0;for(int i=1;i<=n;i++) tn[++ut]=Y[i];
	sort(tn+1,tn+ut+1),yt=ut=unique(tn+1,tn+ut+1)-tn-1;
	for(int i=1;i<=n;i++) Y[i]=lower_bound(tn+1,tn+ut+1,Y[i])-tn;
	for(int i=1;i<=yt;i++) v[i].push_back(1);
	for(int i=1;i<=n;i++) v[Y[i]].push_back(X[i]);
	for(int i=1;i<=yt;i++) v[i].push_back(xt+1);
	for(int i=yt;i>=1;i--)
	{
		sort(v[i].begin(),v[i].end());
		//{for(auto x:v[i]) printf("%d ",x);putchar('\n');}
		for(int j=1;j<(int)v[i].size()-1;j++)
		{
			if(!vs[v[i][j]]) add(v[i][j],1),vs[v[i][j]]=1;
			rs+=1ll*q(1,v[i][j])*q(v[i][j],v[i][j+1]-1);
			//printf("%d,%d : %d*%d\n",i,v[i][j],q(1,v[i][j]),q(v[i][j],v[i][j+1]-1));
		}
	}
	return printf("%lld\n",rs),0;
}
posted @ 2021-08-07 13:10  Peal_Frog  阅读(31)  评论(0编辑  收藏  举报