版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34283998/article/details/82859778
比较有思维难度的一道题,绞了好久.
首先先不考虑双向的轨道,记第i条轨道需要的行驶时间为 ,从左边出发的车在i停留 ,从右边出发的车停留 .那么如果当前的这条轨道 x 没有发生冲突就可以转换为使区间 与区间 没有交点.
可以式子进行变形,然后我们又可以通过调节k,使得这两个区间变为 和 .
记 ,通过不等式化简可以得到,上述条件可以看作 不在区间 中.取个补集,然后就要求 到最小的一个满足要求的位置(即左端点),用线段树维护一下.然后dp一下答案.
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll MAXN=100005;
const ll INF=0x3f3f3f3f;
ll n,K,tot;
ll sum[MAXN];
ll f[MAXN],l[MAXN],r[MAXN];
ll num[MAXN*2];
struct node{
ll val,tag;
node *ch[2];
void PushDown(){
if(!tag) return;
if(ch[0]) ch[0]->val=ch[0]->tag=tag;
if(ch[1]) ch[1]->val=ch[1]->tag=tag;
val=tag;
tag=0;
}
}tree[MAXN*4];
node *root,*ncnt;
void Init(){ncnt=&tree[0];}
node *newnode(ll val=0){
node *p=++ncnt;
p->val=val,p->tag=0;
p->ch[0]=p->ch[1]=NULL;
return p;
}
void Update(node *&rt,ll l,ll r,ll st,ll ed,ll val){
if(st>ed) return;
if(!rt) rt=newnode();
if(st<=l&&r<=ed){
rt->val=rt->tag=val;
return;
}
if(!rt->ch[0]) rt->ch[0]=newnode();
if(!rt->ch[1]) rt->ch[1]=newnode();
rt->PushDown();
ll mid=(l+r)>>1;
if(st<=mid) Update(rt->ch[0],l,mid,st,ed,val);
if(ed>mid) Update(rt->ch[1],mid+1,r,st,ed,val);
}
ll Query(node *rt,ll l,ll r,ll pos){
if(!rt) return 0;
if(l==r) return rt->val;
ll mid=(l+r)>>1;
if(!rt->ch[0]) rt->ch[0]=newnode();
if(!rt->ch[1]) rt->ch[1]=newnode();
rt->PushDown();
if(pos<=mid) return Query(rt->ch[0],l,mid,pos);
return Query(rt->ch[1],mid+1,r,pos);
}
ll Ask(ll k){
ll pos=Query(root,1,tot,k);
return pos?f[pos]+(num[l[pos]]-num[k]+K)%K:0;
}
int main(){
Init();
scanf("%lld%lld",&n,&K);
for(ll i=1;i<=n;i++){
ll a,b;
scanf("%lld%lld",&a,&b);
sum[i]=sum[i-1]+a;
if(b==2) l[i]=0,r[i]=K-1;
else l[i]=(K-2ll*sum[i-1]%K)%K,r[i]=(K-2ll*sum[i]%K)%K;
if(b==1&&a*2ll>K) return puts("-1"),0;
num[++tot]=l[i];
num[++tot]=r[i];
}
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]) Update(root,1,tot,r[i]+1,l[i]-1,i);
else Update(root,1,tot,1,l[i]-1,i),Update(root,1,tot,r[i]+1,tot,i);
}
ll ans=f[1];
for(ll i=tot;i>0;i--) ans=min(ans,Ask(i));
printf("%lld\n",ans+2ll*sum[n]);
}