Codeforces Round #111 (Div. 2) E. Buses and People 线段树|多维限制|离散化

一看发现要求满足3个条件,有点头大
可以先把所有的bus和people拎出来,用bus的s和people的l去排序,这样能保证对于当前的people,si都合法。
然后考虑如何满足ti最小的情况下,使得fi>=bj,且ti>=rj
思想有点像dp,dp里解决二维问题,一问是拿下标做状态,然后搞偏序或者LIS什么的
联想到这里也可以拿ti做下标,那么只要把ti的范围限制在[rj,max],在这个区间上找最小的fi>=bj
就变成一个经典的线段树递归问题,如果左区间满足,直接去左区间;否则去找右区间(这样能保证ti最小)
ps.有笨蛋数组开小了导致超时了,是谁我不说:)记得加区间max剪枝保证复杂度。
 
 
复制代码
#include<bits/stdc++.h>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=2e5+5;
int ans[maxn],lisan[maxn<<1];
struct seg{
    int l,r,mx,at;
    //
}t[maxn<<2];
struct Bus{
    int s,f,t;
}bus[maxn];
struct Peo{
    int l,r,b;
}p[maxn];
void push_up(int rt){
    t[rt].mx=max(t[ls].mx,t[rs].mx);
}
void build(int rt,int l,int r){
    t[rt].l=l;t[rt].r=r;
    if(l==r){
       t[rt].mx=0;
       t[rt].at=0;
       return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
}
void update(int rt,int l,int r,int val,int id){
    //cout<<rt<<" "<<t[rt].l<<" "<<t[rt].r<<" "<<val<<endl;
    if(l<=t[rt].l&&t[rt].r<=r){
        // update
        if(t[rt].mx<val){
            t[rt].mx=val;
            t[rt].at=id;
        }
        //cout<<"finish"<<t[rt].mx<<" "<<t[rt].at<<endl;
        return;
    }
    if(t[ls].r>=l) update(ls,l,r,val,id);
    if(t[rs].l<=r) update(rs,l,r,val,id);
    push_up(rt);
}
int ask(int rt,int l,int r,int x){
    if(l<=t[rt].l&&t[rt].r<=r){
       if(t[rt].mx<x) return 0;
    }
    if(t[rt].l==t[rt].r){
        if(t[rt].mx>=x) return t[rt].at;
        else return 0;//
    }
    int ans=0;
    if(t[ls].r>=l&&t[ls].mx>=x) ans=ask(ls,l,r,x);//
    if(ans) return ans;
    if(t[rs].l<=r&&t[rt].mx>=x) ans=ask(rs,l,r,x);//
    return ans;
}
int n,m;
struct lys{
    int pos,type;
};
// find the smallest ti that fi>=ri && ti>=bi
int main(){
    //freopen("lys.in","r",stdin);
    fastio;
    cin>>n>>m;
    vector<lys>s;
    for(int i=1;i<=n;i++){
        cin>>bus[i].s>>bus[i].f>>bus[i].t;
        s.emplace_back((lys){bus[i].s,i});
        lisan[i]=bus[i].t;
    }
    for(int i=1;i<=m;i++){
        cin>>p[i].l>>p[i].r>>p[i].b;
        s.emplace_back((lys){p[i].l,n+i});
        lisan[i+n]=p[i].b;
    }
    sort(lisan+1,lisan+n+m+1);
    int len=unique(lisan+1,lisan+n+m+1)-(lisan+1);
    build(1,1,len);
    sort(s.begin(), s.end(), [&](const lys &lhs, const lys& rhs) {
        if(lhs.pos == rhs.pos) return lhs.type < rhs.type;
        return lhs.pos < rhs.pos;
    });
    for(auto it:s){
        int fir=it.pos,se=it.type;
        //cout<<fir<<" "<<se<<endl;
        if(se<=n){// bus
            int pos=lower_bound(lisan+1,lisan+1+len,bus[se].t)-lisan;
            update(1,pos,pos,bus[se].f,se);
        }
        else {
            se-=n;//people
            int pos=lower_bound(lisan+1,lisan+1+len,p[se].b)-lisan;
            ans[se]=ask(1,pos,len,p[se].r);
            if(!ans[se]) ans[se]=-1;
        }
    }
    for(int i=1;i<=m;i++) cout<<ans[i]<<" ";
} 
复制代码

 

posted @   liyishui  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示