「RCOI2019」Rochine Round 1 T2解析
引领天下
2019-12-09 20:57:19
这个题的 idea 其实很早以前就有了,但是由于某团的特性一直到现在才与大家见面
题意我就不复述了,直接谈做法
这个题首先给人不舒服的地方就是在于这个环形跑道不准超车,这就导致如果安排不当的话是完全可以造成堵车的。那么怎么解决这个问题呢?
一个神奇的思想出现了:
**把所有车和货物全部拉到 $\mathbf{0}$ 号点!**
那么,一个 $t$ 时刻在 $i$ 位置出现的货物实际上等价于一个 $t-i$ 时刻在 $0$ 位置 出现的货物。
接下来的事情就很简单啦,我们对当前的小车建立一个小根堆,初始是 $m$ 个 $0$,然后对货物按拉到 $0$ 位置之后出现的时间排序,派出当前空闲的最靠前的小车去接,接完之后将小车跑一圈回来到达 $0$ 位置的时间重新 push 进小车的堆即可。
代码:
```cpp
#include<bits/stdc++.h>
using namespace std;
long long n,m,k,num,a[10000005];
priority_queue<long long,vector<long long>,greater<long long>>q;//小车的堆
struct control{
int ct,val;
control(int Ct,int Val=-1):ct(Ct),val(Val){}
inline control operator()(int Val){return control(ct,Val);}
}_endl(0),_prs(1),_setprecision(2);
struct FastIO{
#define IOSIZE 1000000
char in[IOSIZE],*p,*pp,out[IOSIZE],*q,*qq,ch[20],*t,b,K,prs;
FastIO():p(in),pp(in),q(out),qq(out+IOSIZE),t(ch),b(1),K(6){}
~FastIO(){fwrite(out,1,q-out,stdout);}
inline char getch(){return p==pp&&(pp=(p=in)+fread(in,1,IOSIZE,stdin),p==pp)?b=0,EOF:*p++;}
inline void putch(char x){q==qq&&(fwrite(out,1,q-out,stdout),q=out),*q++=x;}
inline void puts(const char str[]){fwrite(out,1,q-out,stdout),fwrite(str,1,strlen(str),stdout),q=out;}
inline void getline(string&s){
s="";
for(register char ch;(ch=getch())!='\n'&&b;)s+=ch;
}
#define indef(T)inline FastIO&operator>>(T&x)\
{\
x=0;register char f=0,ch;\
while(!isdigit(ch=getch())&&b)f|=ch=='-';\
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getch();\
return x=f?-x:x,*this;\
}
indef(int)
indef(long long)
inline FastIO&operator>>(char&ch){return ch=getch(),*this;}
inline FastIO&operator>>(string&s){
s="";
register char ch;
while(isspace(ch=getch())&&b);
while(!isspace(ch)&&b)s+=ch,ch=getch();
return*this;
}
inline FastIO&operator>>(double&x){
x=0;
register char f=0,ch;
double d=0.1;
while(!isdigit(ch=getch())&&b)f|=(ch=='-');
while(isdigit(ch))x=x*10+(ch^48),ch=getch();
if(ch=='.')while(isdigit(ch=getch()))x+=d*(ch^48),d*=0.1;
return x=f?-x:x,*this;
}
#define outdef(_T)inline FastIO&operator<<(_T x)\
{\
!x&&(putch('0'),0),x<0&&(putch('-'),x=-x);\
while(x)*t++=x%10+48,x/=10;\
while(t!=ch)*q++=*--t;\
return*this;\
}
outdef(int)
outdef(long long)
inline FastIO&operator<<(char ch){return putch(ch),*this;}
inline FastIO&operator<<(const char str[]){return puts(str),*this;}
inline FastIO&operator<<(const string&s){return puts(s.c_str()),*this;}
inline FastIO&operator<<(double x){
register int k=0;
this->operator<<(int(x));
putch('.');
x-=int(x);
prs&&(x+=5*pow(10,-K-1));
while(k<K)putch(int(x*=10)^48),x-=int(x),++k;
return*this;
}
inline FastIO&operator<<(const control&cl){
switch(cl.ct){
case 0:putch('\n');break;
case 1:prs=cl.val;break;
case 2:K=cl.val;break;
}
}
inline operator bool(){return b;}
}io;//快读
int main(){
io>>n>>m;
for(long long i=1;i<=n;i++){
for(io>>k;k;k--){
num++;
io>>a[num];
a[num]-=i;//读入的同时就把货物拉到0位置,出现的时间-=小车跑到货物原始位置的时间(即货物原始位置)
}
}
sort(a+1,a+num+1);//对拉到0位置之后的货物按时间排序
for(long long i=1;i<=m;i++)q.push(0);//丢m个0(每个小车初始的最早可出发时间都为0)
for(long long i=1;i<=num;i++){
long long t=q.top();//取出堆顶的车,pop掉
q.pop();
q.push(max(t,a[i])+n+1);//车能出发的时间要和货物出现的时间取max
}
while(q.size()>1)q.pop();//最后堆中剩下的可出发时间最迟的小车即为答案
io<<q.top();
return 0;
}
```
#### 关于本题
- 出题人太菜了,本来花0.5h想了个分类讨论的dp,打算实现的时候发现太麻烦了于是去找Sooke,Sooke神仙花了10min给出了题解中这个做法并爆踩了标算。(Sooke太强辣!)
- 本题的卡常并不是我一个人决定的(大雾,我当时要调时限的时候Karry5307坚决反对(企图甩锅)
![](https://i.loli.net/2019/12/09/Ys6Zzf2IWHBwbva.png)
为此,作者还受到了神虎的强烈谴责
![](https://i.loli.net/2019/12/09/mAUgTSZnfJpMkYe.png)
~~我太难了~~