官方题解:
因为有两维的限制,所以我们先按 ai 从大到小排一下序,
对于排序后的第 i 个妹子,她的排名就是 max{rk[j]}+1 (bj>bi),
那么我们把排名 bi 当成下标,把 rki 当成值,用线段树维护一下区间 max 即可。
将bi排序,将每个妹子对应的bi变成排序后bi的编号,,对ai进行从大到小排序。
i 从 0 到 n 遍历,对于每个妹子,将她插入线段树中,妹子的重要程度为区间(bi,n)的最大值 + 1,然后将妹子的重要程度更新到bi位置。
模拟:
妹子0,查询线段树中区间(bi,n)的最大值,此时线段树中每个节点都是0,所以妹子0的重要程度为 1 ,然后将妹子0的重要程度更新到bi位置。。由于对ai进行从大到小排序,所以妹子0重要程度肯定1。
妹子1,查询线段树中区间(bj,n)的最大值,如果bj < bi,那么妹子1 的重要程度为 2,因为妹子0的细心和热心程度都大于妹子1 。如果bj > bi ,那么区间(bj,n)的最大值为 0 ,妹子1 的重要程度为 1 。因为除了妹子0,没有人比妹子1的a大,但是妹子0的b小于妹子1。妹子1 的重要程度为 1 正确。 然后将妹子1 的重要程度更新到bj位置。
#include<bits/stdc++.h>
using namespace std;
#define Mid (l+r>>1)
#define Lson (id<<1)
#define Rson (id<<1|1)
#define Left Lson,l,Mid
#define Right Rson,Mid+1,r
const int N = 1e5+10;
int n;
int tree[4*N];
int b[N];
int res[N];
struct node{
int a, b, id;
}e[N];
bool cmp(node x, node y){
return x.a > y.a;
}
void update(int id, int l, int r, int pos, int val){
if(l==r){
tree[id] = val;
return ;
}
if(pos <= Mid) update(Left,pos,val);
else update(Right,pos,val);
tree[id]=max(tree[Lson], tree[Rson]);
}
int query(int id, int l, int r, int ql, int qr){
if(ql <= l && r <= qr){
return tree[id];
}
int ans = 0;
if(ql <= Mid) ans = max(ans, query(Left,ql,qr));
if(qr > Mid) ans = max(ans, query(Right,ql,qr));
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin >> n;
for(int i = 0; i < n; i++){
cin >> e[i].a >> e[i].b;
e[i].id = i;
b[i] = e[i].b;
}
sort(b,b+n);
int len = unique(b,b+n) - b;
for(int i = 0; i < n; i++){
e[i].b = lower_bound(b,b+len,e[i].b) - b+1;
}
sort(e, e+n, cmp);
for(int i = 0; i < n; i++){
res[e[i].id] = query(1,1,n,e[i].b,n)+1;
update(1,1,n,e[i].b,res[e[i].id]);
}
for(int i = 0; i < n; i++)
cout << res[i] << "\n";
return 0;
}