AGC011 F Train Service Planning - 线段树

不算神仙的神仙题
网上题解写的很清楚了
(lhx必须%)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<climits>
#define N 100010
#define gc getchar()
#define lint long long
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
lint s[N],f[N];int a[N],b[N],L[N],R[N],Lid[N],Rid[N];vector<int> v;
inline int getid(int x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1; }
struct segment{int l,r,v;segment *ch[2];}*rt;
int build(segment* &rt,int l,int r)
{
    rt=new segment,rt->l=l,rt->r=r,rt->v=0;int mid=(l+r)>>1;if(l==r) return 0;
    return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r);
}
inline int push_down(segment* &rt) { return rt->ch[0]->v=rt->ch[1]->v=rt->v,rt->v=0; }
int update(segment* &rt,int s,int t,int v)
{
    if(s>t) return 0;int l=rt->l,r=rt->r,mid=(l+r)>>1;
    if(s<=l&&r<=t) return rt->v=v;if(rt->v) push_down(rt);
    if(s<=mid) update(rt->ch[0],s,t,v);if(mid<t) update(rt->ch[1],s,t,v);return 0;
}
int query(segment* &rt,int p) { int l=rt->l,r=rt->r,mid=(l+r)>>1;if(l==r||rt->v) return rt->v;return query(rt->ch[p>mid],p); }
int main()
{
    int n=inn(),k=inn();
    rep(i,1,n) a[i]=inn(),b[i]=inn(),s[i]=s[i-1]+a[i];
    rep(i,1,n) if(b[i]==1&&a[i]*2>k) return !printf("-1\n");
    for(int i=1;i<=n;v.pb(L[i]),v.pb(R[i]),i++)
        if(b[i]==2) L[i]=0,R[i]=k-1;
        else R[i]=(k-2*s[i]%k)%k,L[i]=(R[i]+2*a[i]%k)%k;
    sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
    build(rt,1,(int)v.size());rep(i,1,n) Lid[i]=getid(L[i]),Rid[i]=getid(R[i]);
    for(int i=n;i;i--)
    {
        int j=query(rt,Lid[i]);
        if(!j) f[i]=0;else f[i]=f[j]+(L[j]-L[i]+k)%k;
        if(L[i]<=R[i]) update(rt,1,Lid[i]-1,i),update(rt,Rid[i]+1,(int)v.size(),i);
        else update(rt,Rid[i]+1,Lid[i]-1,i);
    }
    lint ans=LLONG_MAX;
    rep(i,0,(int)v.size()-1)
    {
        int x=query(rt,i+1);if(!x) { ans=0;break; }
        else ans=min(ans,f[x]+(L[x]-v[i]+k)%k);
    }
    return !printf("%lld\n",ans+2*s[n]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值