洛谷P3602 Koishi Loves Segments(贪心,set)

洛谷题目传送门

贪心小水题。

把线段按左端点从小到大排序,限制点也是从小到大排序,然后一起扫一遍。

对于每一个限制点实时维护覆盖它的所有线段,如果超过限制,则贪心地把右端点最大的线段永远删去,不计入答案。显然这样做对后面的决策更有利。

以右端点为键值,需要资瓷动态插入,删除最小值、最大值,set就行了。

代码很短,常数应该比较大,但不知为何暂时混了个rk1。

#include<bits/stdc++.h>
#define R register int
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
using namespace std;
const int SZ=1<<19,N=4e5+9;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
    G;while(*ip<'-')G;
    R f=*ip=='-';if(f)G;
    R x=*ip&15;G;
    while(*ip>'-'){x*=10;x+=*ip&15;G;}
    return f?-x:x;
}
struct Seg{
    int x,y;
    inline bool operator<(const Seg&a)const{
        return x<a.x;
    }
}a[N],b[N];
struct Cmp{
    inline bool operator()(R i,R j){//比较函数要比下标,不然可能会因为y相同被判等
        return a[i].y<a[j].y||(a[i].y==a[j].y&&i<j);
    }
};
set<int,Cmp>s;
int main(){
    R n=in(),m=in(),ans=n;
    for(R i=0;i<n;++i)a[i].x=in(),a[i].y=in();
    for(R i=0;i<m;++i)b[i].x=in(),b[i].y=in();
    sort(a,a+n);sort(b,b+m);
    for(R i=0,j=0;i<m;++i){
        while(j<n&&a[j].x<=b[i].x)s.insert(j++);
        while(s.size()&&a[*s.begin()].y<b[i].x)s.erase(s.begin());
        while(s.size()>b[i].y)s.erase(*s.rbegin()),--ans;
    }
    return cout<<ans<<endl,0;
}

猜你喜欢

转载自www.cnblogs.com/flashhu/p/10573808.html
今日推荐