[Agc011F] Train Service Planning

题目大意:

有n+1个车站,n条轨道,第i条轨道联通i-1和i车站,通过它要花a[i]时间,这条轨道有b[i]=1或2条车道,也就是说,他是单向还是双向的。

要满足以下约定

  • 所有的火车要么从站台0到站台n,要么从站台n到站台0
  • 对任意终点为n的火车,如果它在t时刻离开站台i−1并开往站台i,那么它必须在t+Ai时刻到达i站台,对反方向要求相同
  • 对任意终点为n的火车,如果它在s时刻到达站台i并在t时刻离开站台i,那么下一列经过站台i的终点为n的火车必须在s+K时刻到达站台i并在t+K时刻离开站台i,对反方向要求相同![]
  • 在任意时刻不能有两列相向而行的火车在单向区间内互相穿过

    要求最小化两种火车从起点到终点的时间和。

    \(n\leq 10^5,a_i\leq 10^9\)

试题分析



不难发现,双向道路上如果有两条线(列车行驶)的交是没有问题的,因为可以双向行驶。

但是单向的话就不行了,需要在某个车站进行等待并交换道路。

然而我们需要求这些车的行驶时间的和,怎么办呢?

一个非常重要的传统办法——列式子。

我们下面把第一辆车称作1号,把第二辆(\(n\to 0\))称作2号。

设\(q_i\)为1号每站的等待时间,\(p_i\)为2号每站的等待时间。

于是有:\(tim_1=\sum_{i=0}^{n-1} q_i+a_i,tim_2=\sum_{i=0}^{n-1} p_i+a_i\)

那么走到其中一个点\(j\)的时间是多少呢?

\[tim_{1,j}=\sum_{i=0}^{j-1} q_i+a_i
\]

\[tim_{2,j}=\sum_{i=0}^{j-1} p_i+a_i
\]

还是没有突破口,继续列式子。。。

发现1号走过\(j-1\to j\)的时间区间是\((\sum_{i=0}^{j-2} q_i+a_i +q_{j-1},\sum_{i=0}^{j-1} q_i+a_i)\)

2号同理。

这个东西乍一看没有办法搞,但是这道题有一个很重要的性质:时间K就是一个循环节。

那么我们就可以把这个东西丢到\(\pmod{k}\)的意义下去做。

既然图上的线不交,就意味着1号和2号的站中间的时间区间不交。

于是继续列出限制条件,然后移项变换,得到:$$\sum_{i=0}^{j}(p[i]+q[i])\not \in[-2s[j],-2(s[j]-a[j])]$$

其中\(s\)为\(a\)的前缀和。

那么问题就变成了:

有一个人,在数轴上走,从左到右每次向右走(可以不走),每次走的地方在\([l_i,r_i]\)中,问代价。

因为是\(\pmod{k}\)意义下,所以可以把两段补区间前后相接得到一个新的区间。

能在原地踏步显然在原地踏步,所以我们需要找的是\([l_j,r_j]\)不包含\(l_i\)的\(j>i\)的区间。

这个东西我们可以线段树的区间覆盖加上贪心dp出来。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
//#include<ctime>
//#include<cmath>
//#include<queue> using namespace std;
#define LL long long inline int read(){
int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const LL INF = 2147483600;
const LL MAXN = 300010; LL N,K;
LL tag[MAXN<<2],col[MAXN<<2]; inline void tage_lazy(LL rt){
if(tag[rt]){
col[rt<<1]=tag[rt]; col[rt<<1|1]=tag[rt];
tag[rt<<1]=tag[rt]; tag[rt<<1|1]=tag[rt];
tag[rt]=0;
}
}
inline void Cover(LL rt,LL l,LL r,LL L,LL R,LL k){
if(L>R) return ;
if(L<=l&&R>=r){tag[rt]=k; col[rt]=k; return ;} tage_lazy(rt);
LL mid=(l+r)>>1; if(L<=mid) Cover(rt<<1,l,mid,L,R,k);
if(R>mid) Cover(rt<<1|1,mid+1,r,L,R,k); return ;
}
inline LL Query(LL rt,LL l,LL r,LL k){
if(l==r) return col[rt]; LL mid=(l+r)>>1; tage_lazy(rt);
if(k<=mid) return Query(rt<<1,l,mid,k);
else return Query(rt<<1|1,mid+1,r,k);
}
LL f[MAXN+1],Num[MAXN<<1];
LL l[MAXN+1],r[MAXN+1],tot;
inline LL Ask(LL k){
LL pos=Query(1,1,tot,k);
return (pos?f[pos]+(Num[l[pos]]-Num[k]+K)%K:0);
}
LL a[MAXN+1],b[MAXN+1],s[MAXN+1]; int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
N=read(),K=read(); tot=0;
for(LL i=1;i<=N;i++){
a[i]=read(),b[i]=read();
s[i]=(s[i-1]+a[i]);
if(b[i]==2){l[i]=0; r[i]=K-1;}
else l[i]=(K-2*s[i-1]%K)%K,r[i]=(K-2*s[i]%K)%K;
if(b[i]==1&&a[i]*2LL>K){puts("-1"); return 0;}
Num[++tot]=l[i]; Num[++tot]=r[i];
//cout<<"x:"<<l[i]<<" "<<r[i]<<endl;
} sort(Num+1,Num+tot+1); tot=unique(Num+1,Num+tot+1)-Num-1;
for(LL i=1;i<=N;i++){
l[i]=lower_bound(Num+1,Num+tot+1,l[i])-Num;
r[i]=lower_bound(Num+1,Num+tot+1,r[i])-Num;
} for(LL i=N;i>=1;i--){
f[i]=Ask(l[i]);
if(l[i]>r[i]) Cover(1,1,tot,r[i]+1,l[i]-1,i);
else Cover(1,1,tot,1,l[i]-1,i),Cover(1,1,tot,r[i]+1,tot,i);
} LL ans=f[1];
for(LL i=tot;i>=1;i--) ans=min(ans,Ask(i));//cout<<i<<": "<<Ask(i)<<endl;
printf("%lld\n",ans+2LL*s[N]);
return 0;
}

[Agc011F] Train Service Planning的更多相关文章

  1. [AGC011F] Train Service Planning [线段树优化dp+思维]

    思路 模意义 这题真tm有意思 我上下楼梯了半天做出来的qwq 首先,考虑到每K分钟有一辆车,那么可以把所有的操作都放到模$K$意义下进行 这时,我们只需要考虑两边的两辆车就好了. 定义一些称呼: 上 ...

  2. 【Atcoder Grand Contest 011 F】Train Service Planning

    题意:给\(n+1\)个站\(0,\dots,n\),连续的两站\(i-1\)和\(i\)之间有一个距离\(A_i\),其是单行(\(B_i=1\))或双行(\(B_i=2\)),单行线不能同时有两辆 ...

  3. 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)

    洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...

  4. [agc011F]Train Service Planning-[线段树优化dp+神秘思考题]

    Description 传送门 Solution 请围观lhx大佬的博客(大佬写的太好了我都没有写的动力了em) Code #include<iostream> #include<c ...

  5. Agc011_F Train Service Planning

    先放题面,再放LHX巨佬题解 接着就是%%%.$orz.Oro.Or2.Otz.OTL.sto.rzo.Jto$.On_.○| ̄|_啊 模拟赛里直接把这道题刚掉了 一题升天·爆踩全场 这题思维跨越度已 ...

  6. AtCoder Grand Contest 011 F - Train Service Planning

    题目传送门:https://agc011.contest.atcoder.jp/tasks/agc011_f 题目大意: 现有一条铁路,铁路分为\(1\sim n\)个区间和\(0\sim n\)个站 ...

  7. NOIp2018模拟赛三十七

    奇怪的一场... 前两题都是全场题,C题明显不可做,我题目都没看懂...(STO lhx OTZ) 成绩:100+100+8=208 貌似十几个208的...A题暴力$O(nmc)$能过...暴力容斥 ...

  8. AtCoder Grand Contest 011

    AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...

  9. A*G/C011

    A*G/C011 A Airport Bus 不会zbl/kk B Colorful Creatures 枚举每个开始的点直接倍增 我好像sb了,可行的是一段前缀所以可以直接2分 C Squared ...

随机推荐

  1. 系统学习(javascript)_基础(语法)

    1.分类 ECMAScript  javascript的标准 DOM  Document object Model文档对象模型 BOM  Browser object Model 浏览器对象模型 ti ...

  2. std 与标准库

    1.命名空间std C++标准中引入命名空间的概念,是为了解决不同模块或者函数库中相同标识符冲突的问题.有了命名空间的概念,标识符就被限制在特定的范围(函数)内,不会引起命名冲突.最典型的例子就是st ...

  3. Centos6.5下搭建nagios详解

    一.LAMP环境部署 1.安装php 1.安装yum源 rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-releas ...

  4. 含有ref out 参数 的方法反射 Emit 与 普通

    反射中很多朋友应该屡屡被带有ref out参数的方法折腾 当使用正常反射一个方法时候: 代码如下调用一个后期绑定方法MakeByRefType 就行了 MemberInfo test = typeof ...

  5. 使用postman做接口测试(二)

    参考大神总结:https://www.cnblogs.com/Skyyj/p/6856728.html 二,下边的东西工作中实际要用到了 1, postman安装 chrome浏览器打开chrome: ...

  6. python网络编程--线程join和Daemon(守护进程)

    一:什么情况下使用join join([timeout])调用join函数会使得主调线程阻塞,直到被调用线程运行结束或超时. 参数timeout是一个数值类型,用来表示超时时间,如果未提供该参数,那么 ...

  7. 写在用Mac进行Java开发之前

    在用Mac进行开发之前,建议浏览以下几个概念. 1. 几个基础概念 - 计算机 计算机(computer)俗称电脑,发明者是约翰·冯·诺依曼,计算机是现代一种用于高速计算的电子计算机器,可以进行数值计 ...

  8. WiFi无线连接真机进行Appium自动化测试方法

    有时需要测试APP 产品的耗电问题,但用自动化又面临了一个USB接电脑供电的问题,从而导致计算出来的功耗与手动跑,存在有很大的误差,因此可使用wifi无线连接到手机进行自动化测试,解决功耗问题. 前提 ...

  9. linux下Ctrl命令组合

    1.键盘组合键操作 ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程.常用于终止正在运行的程序. ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程.  ...

  10. **PHP错误Cannot use object of type stdClass as array in错误的

    错误:将PHP对象类型当做了PHP数组  解决方法:用对象操作符-> 今天在PHP输出一个二维数组的时候,出现了“Fatal error: Cannot use object of type s ...