其他分享
首页 > 其他分享> > 【2022 杭电多校】第五场 1012 Buy Figurines 【模拟】

【2022 杭电多校】第五场 1012 Buy Figurines 【模拟】

作者:互联网

链接

https://acm.hdu.edu.cn/showproblem.php?pid=7196

思路

  1. 读题后发现,由于每个人的到达时间不同,且可以唯一确定加入的队伍,所以每个人选择加入的队伍是确定的
    那么只需要(按事件发生的时间顺序)模拟即可,使用优先队列

定义三元组<time,type,id> 把所有入队、出队操作看成操作序列,按照发生的时间先后排序;type用来标识入队还是出队,先出再入;id表示人或者队伍的编号

注意优先队列默认是按优先级从大到小的顺序排列,我为了让数值小的排在前面,在这里重载小于号的函数内部写大于,表示值大的反而优先级低

struct node{
    ll t;
    int type;
    int id;
    bool operator <(const node& b)const{
        if(t!=b.t) return t>b.t;
        else if(type!=b.type) return type>b.type;
        else{
            if(type==1) return a[type].st>a[b.type].st;
            else return id>b.id;
        }
    }
};
priority_queue<node>op;
  1. 模拟的同时需要查询当前人数最少的队伍,需要借助查询时间<O(n)的数据结构,使用set或者线段树等等

线段树:
再开一个数据实时记录人数,并用线段树维护区间最小值,需要查找最小值对应的编号时再写个二分就行

int l=1,r=m,mid,ind;
   while(l<=r){
   mid=(l+r)>>1;
   ll vl=query(l,mid,1,m,1),vr=query(mid+1,r,1,m,1);
   if(vl<=vr){
       r=mid;
   }
   else if(vl>vr){
       l=mid+1;
   }
   if(l==r){
       ind=l;
       break;
   }
}

set:
存储<队伍人数,队伍id>,按照队伍人数降序顺序排
还需要记录每个人对应的队伍

struct Queue{
    int num;
    int id;
    bool operator < (const Queue &aa) const{
        if(num!=aa.num) return num<aa.num;
        else return id<aa.id;
    }
}q[N];
set<Queue>st;

code

线段树:

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 2e5+10;
int T,n,m;
struct peo{
    int st;
    int len;
    int id;
    bool operator < (const peo &aa) const{
        return st<aa.st;
    }
}a[N];
ll wait[N],tim[N];

struct node{
    ll t;
    int type;
    int id;
    bool operator >(const node& b)const{
        if(t!=b.t) return t>b.t;
        else if(type!=b.type) return type>b.type;
        else{
            if(type==1) return a[type].st>a[b.type].st;
            else return id>b.id;
        }
    }
};
priority_queue<node,vector<node>,greater<node> >q;

struct SegTree{
    ll v;
    ll lazy;
}t[N<<2];

void push_up(int rt){
    t[rt].v=min(t[rt*2].v,t[rt*2+1].v);
}

void build(int l,int r,int rt){
    t[rt].lazy=0;
    if(l==r){
        t[rt].v=wait[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
    push_up(rt);
}

void upd(int L,int R,int l,int r,int rt,ll v){
    if(l>R||r<L||l>r) return;
    if(l==r){
        t[rt].v=v;
        return;
    }
    int mid=(l+r)>>1;
    upd(L,R,l,mid,rt*2,v);
    upd(L,R,mid+1,r,rt*2+1,v);
    push_up(rt);
}

ll query(int L,int R,int l,int r,int rt){
    if(L>r||R<l||l>r) return 1e18;
    if(L<=l&&r<=R){
        return t[rt].v;
    }
    int mid=(l+r)>>1;
    return min(query(L,R,l,mid,rt*2),query(L,R,mid+1,r,rt*2+1));
}

int main(){
    int T; cin>>T;
    while(T--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i].st,&a[i].len);
            a[i].id=i;
            q.push({a[i].st,2,i});  //st_time
        }

        for(int i=1;i<=m;i++){
            wait[i]=0;
            tim[i]=0;
        }
        build(1,m,1);
        while(!q.empty()){   //<time,type,id>
            auto now=q.top();
            q.pop();
            if(now.type==1){
                wait[now.id]--;
                upd(now.id,now.id,1,m,1,wait[now.id]);
            }
            else{
                int l=1,r=m,mid,ind;
                while(l<=r){
                    mid=(l+r)>>1;
                    ll vl=query(l,mid,1,m,1),vr=query(mid+1,r,1,m,1);
                    if(vl<=vr){
                        r=mid;
                    }
                    else if(vl>vr){
                        l=mid+1;
                    }
                    if(l==r){
                        ind=l;
                        break;
                    }
                }

                if(tim[ind]<a[now.id].st) tim[ind]=a[now.id].st;
                tim[ind]+=a[now.id].len;
                q.push(node{tim[ind],1,ind});
                wait[ind]++;
                upd(ind,ind,1,m,1,wait[ind]);              
            }
        }   
        ll ans=0;
        for(int i=1;i<=m;i++){
            ans=max(ans,tim[i]);
        }
        printf("%lld\n",ans);
    }

    system("pause");
    return 0;
}

set:

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 2e5+10;
int T,n,m;
struct peo{
    int st;
    int len;
    int id;
}a[N];
ll tim[N];  //总时间
int q_select[N];  //编号为i的人对应的队列(是确定的)

struct node{
    ll t;
    int type;
    int id;
    bool operator <(const node& b)const{
        if(t!=b.t) return t>b.t;
        else if(type!=b.type) return type>b.type;
        else{
            if(type==1) return a[type].st>a[b.type].st;
            else return id>b.id;
        }
    }
};
priority_queue<node>op;

struct Queue{
    int num;
    int id;
    bool operator < (const Queue &aa) const{
        if(num!=aa.num) return num<aa.num;
        else return id<aa.id;
    }
}q[N];
set<Queue>st;

int main(){
    int T; cin>>T;
    while(T--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i].st,&a[i].len);
            a[i].id=i;
            op.push({a[i].st,2,i});  //st_time
        }
        st.clear();
        for(int i=1;i<=m;i++){   //ed_time
            st.insert({0,i});
            tim[i]=0;
            q[i]={0,i};
        }
        while(!op.empty()){   //<time,type,id>
            auto now=op.top();
            op.pop();
            if(now.type==1){  //走
                int qid=q_select[now.id];
                st.erase({q[qid].num,q[qid].id});
                q[qid].num--;
                st.insert({q[qid].num,q[qid].id});
            }
            else{  //来
                auto q_front=*st.begin();
                st.erase(q_front);
                int ind=q_front.id;
                q_select[now.id]=ind;
                if(tim[ind]<a[now.id].st) tim[ind]=a[now.id].st;
                tim[ind]+=a[now.id].len;
                op.push({tim[ind],1,now.id});
                q[ind].num+=1;
                q_front.num+=1;
                st.insert(q_front);
            }
        }   
        ll ans=0;
        for(int i=1;i<=m;i++){
            ans=max(ans,tim[i]);
        }
        printf("%lld\n",ans);
    }

    system("pause");
    return 0;
}

标签:杭电多校,Buy,return,int,第五场,mid,st,type,id
来源: https://www.cnblogs.com/re0acm/p/16546121.html