【2022 杭电多校】第五场 1012 Buy Figurines 【模拟】
作者:互联网
链接
https://acm.hdu.edu.cn/showproblem.php?pid=7196
思路
- 读题后发现,由于每个人的到达时间不同,且可以唯一确定加入的队伍,所以每个人选择加入的队伍是确定的
那么只需要(按事件发生的时间顺序)模拟即可,使用优先队列
定义三元组<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;
- 模拟的同时需要查询当前人数最少的队伍,需要借助查询时间<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