CF730G Car Repair Shop
题意
有 个请求,每次请求一个区间 :
-
如果该区间完全没有被占用,占用该区间。
-
如果该区间有位置已经被占用,占用另一个长度为 ,左端点最小的且完全未被占用的区间。
求出每个请求占用的区间。
分析
我们需要进行的操作有:
-
查询某个区间是否被用过。
-
插入某个已知边界的区间。
-
插入某个已知长度的区间。
由于有插入操作的存在,所以我们需要一个支持在任意位置插入元素、查询元素的数据结构,可以看到 最大只有 ,所以我们可以使用链表来实现。
struct Q{
int nxt;//下一个节点
ll l,r;//左右边界
}a[N];
初始化
一开始,令整个链表只有两个节点 和 ,分别是起点和终点,节点 中的区间是 ,节点 中的区间是 ,由题目中的数据可以算出题目所用的区间一定在这两个之间。
a[0].l=a[0].r=0;
a[1].l=a[1].r=1ll*1e5*1e5;
a[0].nxt=1;
a[1].nxt=0;
查询某个区间是否被用过
设查询 是否被占用。
依次遍历每个节点,如果某个区间 满足以下条件,说明它查询区间被占用,立即结束。
-
且 : 的左部分被别的区间占用。
-
且 : 的右部分被别的区间占用。
-
且 : 的中部分被别的区间占用。
bool find(ll l,ll r){
for(int i=a[0].nxt;i;i=a[i].nxt)
if((l>=a[i].l&&l<=a[i].r)||(r>=a[i].l&&r<=a[i].r)||(l<=a[i].l&&r>=a[i].r))
return 1;
return 0;
}
插入某个已知边界的区间
设插入区间 。
依次遍历每个节点 ,并记录它的下一个节点 ,如果 在两个区间之间的区间中,即 且 ,就插入这个区间。
注意新的区间可能比之前的更小,所以遍历要从 节点开始。
void insert1(ll l,ll r){
for(int i=0;a[i].nxt;i=a[i].nxt){
int j=a[i].nxt;
if(a[i].r<l&&r<a[j].l){
a[++t].l=l;
a[t].r=r;
a[i].nxt=t;
a[t].nxt=j;
return;
}
}
}
插入某个已知长度的区间
设插入区间长度为 。
同样依次遍历每个节点 ,并记录它的下一个节点 ,如果这两个区间之间的区间大于等于 的,即 ,就插入这个区间,并用 记录答案。
同样注意新的区间可能比之前的更小,所以遍历要从 节点开始。
void insert2(ll len){
for(int i=0;a[i].nxt;i=a[i].nxt){
int j=a[i].nxt;
if(a[j].l-a[i].r-1>=len){
al=a[++t].l=a[i].r+1;
ar=a[t].r=a[t].l+len-1;
a[i].nxt=t;
a[t].nxt=j;
return;
}
}
}
时间复杂度 。
代码
#include<bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int N=210;
int n,t=1;
ll s,d,al,ar;
struct Q{
int nxt;
ll l,r;
}a[N];
bool find(ll l,ll r){
for(int i=a[0].nxt;i;i=a[i].nxt)
if((l>=a[i].l&&l<=a[i].r)||(r>=a[i].l&&r<=a[i].r)||(l<=a[i].l&&r>=a[i].r))
return 1;
return 0;
}
void insert1(ll l,ll r){
for(int i=0;a[i].nxt;i=a[i].nxt){
int j=a[i].nxt;
if(a[i].r<l&&r<a[j].l){
a[++t].l=l;
a[t].r=r;
a[i].nxt=t;
a[t].nxt=j;
return;
}
}
}
void insert2(ll len){
for(int i=0;a[i].nxt;i=a[i].nxt){
int j=a[i].nxt;
if(a[j].l-a[i].r-1>=len){
al=a[++t].l=a[i].r+1;
ar=a[t].r=a[t].l+len-1;
a[i].nxt=t;
a[t].nxt=j;
return;
}
}
}
int main(){
a[0].l=a[0].r=0;
a[1].l=a[1].r=1ll*1e5*1e5;
a[0].nxt=1;
a[1].nxt=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s>>d;
if(find(s,s+d-1)){
insert2(d);
cout<<al<<" "<<ar<<endl;
}
else{
insert1(s,s+d-1);
cout<<s<<" "<<s+d-1<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号