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;
	}
posted @ 2021-04-21 15:47  Tony_Double_Sky  阅读(35)  评论(0编辑  收藏  举报