​传送门​

题意:是中文,自己看.


定义 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;
}