这题比较卡时间,此外也学到了两种数据结构的使用
题目: 分配资源ID
法一: 正常模拟+延迟更新的思想
AC code
#include<bits/stdc++.h>
using namespace std;
int l, r, t;
// 模拟,按题目意思一步一步来?
int main(){
cin >> l >> r;
vector<bool> exist(r-l+1, true);//id是否空闲
// 用于延迟删除,我们在指定分配id是就可以不急着让该id出来
vector<int> count(r-l+1,1);//每个id在队列中的数量 这个count数组很巧妙!
//count和exist共同保证了延迟删除的可行性!
int free = r - l + 1;//空闲id数量
queue<int> q;
for(int i = l; i <=r; i++) q.push(i);//所有空闲id在一个队列中
cin >> t;
while(t--){
int op, x;
cin >> op >> x;
if(op == 1){
if(x > free) continue; //空闲资源不足,不操作
while(x){
//逐一分配空闲id
int id = q.front();
q.pop();
count[id - l]--;
//因为延迟删除,所以队列中的可能已经被删了或者后面放进去的才是合法的那个id
if(!exist[id-l]||count[id-l]>0) continue;
free--;
exist[id - l] = false;
x--;//这时候才完成一个id的动态分配
}
}else if(op == 2){
if(x<l||x>r||!exist[x-l]) continue;//无需操作
free--;
exist[x - l] = false;
}else if(op == 3){
if(x<l||x>r||exist[x-l]) continue;
q.push(x);
exist[x-l] = true;
count[x-l]++;
free++;
}
}
//注意!还要检验队列头部是否是延迟删除的!
while(1){
int t = q.front();
q.pop();
count[t-l]--;
//重复的id只有最后一个才是合法的
if(exist[t-l]&&count[t-l]==0) {
cout<<t;
return 0;
}
}
}
法二 双向链表(需要快读才能过时间限制)
AC code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
//双向链表+hash写法
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57)
{
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>=48&&ch<=57)
x=x*10+ch-48,ch=nc();
return x*f;
}
void write(int x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
int l, r, t;
// 模拟,按题目意思一步一步来?
int main(){
//cin >> l >> r;
l=read();
r=read();
vector<bool> exist(r-l+1, true);//id是否空闲
// 用于延迟删除,我们在指定分配id是就可以不急着让该id出来
vector<int> count(r-l+1,1);//每个id在队列中的数量 这个count数组很巧妙!
//count和exist共同保证了延迟删除的可行性!
int free = r - l + 1;//空闲id数量
queue<int> q;
for(int i = l; i <=r; i++) q.push(i);//所有空闲id在一个队列中
//cin >> t;
t=read();
while(t--){
int op, x;
//cin >> op >> x;
op=read();
x=read();
if(op == 1){
if(x > free) continue; //空闲资源不足,不操作
while(x){
//逐一分配空闲id
int id = q.front();
q.pop();
count[id - l]--;
//因为延迟删除,所以队列中的可能已经被删了或者后面放进去的才是合法的那个id
if(!exist[id-l]||count[id-l]>0) continue;
free--;
exist[id - l] = false;
x--;//这时候才完成一个id的动态分配
}
}else if(op == 2){
if(x<l||x>r||!exist[x-l]) continue;//无需操作
free--;
exist[x - l] = false;
}else if(op == 3){
if(x<l||x>r||exist[x-l]) continue;
q.push(x);
exist[x-l] = true;
count[x-l]++;
free++;
}
}
//注意!还要检验队列头部是否是延迟删除的!
while(1){
int t = q.front();
q.pop();
count[t-l]--;
//重复的id只有最后一个才是合法的
if(exist[t-l]&&count[t-l]==0) {
//cout<<t;
write(t);
return 0;
}
}
}
附录: 快读/快写模板
快读
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
int x=0,f=1;
char ch=nc();
while(ch<48||ch>57)
{
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>=48&&ch<=57)
x=x*10+ch-48,ch=nc();
return x*f;
}
快写模板
void write(int x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
手动打开O2优化
#pragma GCC optimize(2)