牛客小白月赛16 F-小石的妹子(二维偏序+线段树)


传送门

题意:是中文,自己看.


定义 r k i rk_i rki​是第 i i i个人的编号

每次找到一些人 i i i满足不存在一个 j j j使得 a j > a i a_j>a_i aj​>ai​且 b j > a i b_j>a_i bj​>ai​

发现这样并不好操作,没有办法每次选一些人出来标记.

换个说法, i i i的 r k i rk_i rki​是那些满足 a j > a i a_j>a_i aj​>ai​且 b j > a i b_j>a_i bj​>ai​人的 m a x ( r k j ) + 1 max(rk_j)+1 max(rkj​)+1

由于是二维偏序的,所以先按照 a a a从大到小排序

此时考虑第 i i i个人,由于 [ i + 1 , n ] [i+1,n] [i+1,n]个人一定不是我们想要的那些 j j j

而 [ 1 , i − 1 ] [1,i-1] [1,i−1]中,只有满足 b j > b i b_j>b_i bj​>bi​的才是符合条件的 j j j,才可以更新。

那么,可以以 b i b_i bi​离散化后为下标, r k i rk_i rki​为值维护一颗线段树

按照 a i a_i ai​从大到小依次加入

那么第 i i i个人的 r k rk rk值肯定不会被 a j a_j aj​小于自己的那些 j j j影响

然后去那些 b j b_j bj​大于自己的去找一个 m a x ( r k j ) max(rk_j) max(rkj​),自己的值就再往上加一就好了

题目保证了所有 a , b a,b a,b不相等

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn = 1e5+10;
struct p{ int x,y,id; }s[maxn];
int b[maxn],n,ans[maxn],w[maxn<<2];
bool com(p a,p b){ return a.x>b.x; }
void update(int rt,int l,int r,int x,int val)
{
	if( l>x||r<x )	return;
	if( l==r && l==x ){ w[rt]=val; return; }
	update(lson,x,val); update(rson,x,val);
	w[rt] = max( w[ls],w[rs] );
}
int ask(int rt,int l,int r,int L,int R)
{
	if( l>=L&&r<=R )	return w[rt];
	if( l>R||r<L )	return 0;
	return max( ask(lson,L,R),ask(rson,L,R) );
}
signed main()
{
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		cin >> s[i].x >> s[i].y;
		s[i].id = i, b[i] = s[i].y;
	}
	sort( s+1,s+1+n,com );
	sort( b+1,b+1+n );
	for(int i=1;i<=n;i++)
		s[i].y = lower_bound( b+1,b+1+n,s[i].y )-b;
	for(int i=1;i<=n;i++)
	{
		ans[ s[i].id ] = ask(1,1,n,s[i].y,n )+1;
		update( 1,1,n,s[i].y,ans[ s[i].id ] );
	}
	for(int i=1;i<=n;i++)	cout << ans[i] << endl;
} 
上一篇:解决plt.title无法显示中文的问题


下一篇:画图