UVA11020 Efficient Solutions
UVA11020 Efficient Solutions
Solution
画个图, 发现若是加入一个点, 则前面的点不能比自己低, 加入后, 后面的点不能比自己高
于是我们想维护一个序列, x递减的基础上y递减
于是在此序列中找前驱后继, 序列可以拿 \(Treap\) 维护增减, 最后 $Treap $ 的大小就是答案
偷懒 \(Treap\) 就拿 \(multiset\) 实现了
Code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#include<set>
#define LL long long
#define REP(i, x, y) for(LL i = (x);i <= (y);i++)
using namespace std;
LL RD(){
LL out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
struct Node{
LL x,y;
inline bool operator <(const Node &rhs)const
{
if(x == rhs.x)return y < rhs.y;
return x < rhs.x;
}
};
Node input;
multiset<Node>s;
multiset<Node>::iterator it;
LL T, num;
void init(){
s.clear();
}
void work(){
num = RD();
REP(i, 1, num){
LL x = RD(), y = RD();
input = (Node){x, y};
it = s.lower_bound(input);//找前驱
if(it == s.begin() || (--it)->y > input.y){//这人是有价值的人
s.insert(input);
it = s.upper_bound(input);//找后继
while(it != s.end() && it->y >= input.y)s.erase(it++);
}
printf("%d\n", s.size());
}
}
int main(){
T = RD();
REP(t, 1, T){
printf("Case #%d:\n", t);
init();
work();
if(t != T)puts("");
}
return 0;
}