2017-2018 ACM-ICPC, NEERC, Moscow Subregional Contest H - Hilarious Cooking [Gym/101611]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z591826160/article/details/84205635

H - Hilarious Cooking [Gym/101611]

题面

在这里插入图片描述

思路

考虑序列中已经放置的最近的一组数 a , b a,b
在这一段中能满足要求的最大值就是先有 a a 上升到极大值再下降到 b + 1 b+1
最小值就是由 a a 下降到极小值(大于等于0)然后在上升到 b 1 b-1
最大值到最小值之间的值都是可以通过一些变换取到的
所以可以维护整个序列解的可行范围
最后需要特判一下已放置的点不在序列最后一个或者不在第一个的情况即可

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e6+7;
ll a[maxn],b[maxn];
int main(){
    ll n,T,m;
    cin>>T>>n>>m;
    for (int i=1;i<=m;i++) {
        cin>>a[i]>>b[i];
    }
    ll r=(b[1]+b[1]+(a[1]-1))*(a[1])/2-b[1];
    ll l=(b[1]+b[1]-(a[1]-1))*(a[1])/2-b[1];
    if (b[1]<a[1]-1) l=b[1]*(b[1]+1)/2-b[1];
    //cout<<"L: "<<l<<' '<<r<<endl;
    for (int i=2;i<=m;i++) {
        ll v=(a[i]-a[i-1]+b[i]+b[i-1])>>1;
        if (abs(b[i]-b[i-1])>a[i]-a[i-1]) {
            cout<<"No"<<endl;
            return 0;
        }
        ll t1=v-b[i-1];
        ll t2=v-b[i];
        //cout<<"VM: "<<i<<' '<<v<<' '<<t1<<' '<<t2<<endl;
        r+=(v+b[i-1])*(t1+1)/2+(v+b[i])*(t2+1)/2+(a[i]-a[i-1]-t1-t2-1)*v-b[i];
        v=max(0ll,(b[i]+b[i-1]-a[i]+a[i-1])/2);
        //cout<<"VN: "<<i<<' '<<v<<endl;
        t1=abs(v-b[i-1]);
        t2=abs(b[i]-v);
        l+=(v+b[i-1])*(t1+1)/2+(v+b[i])*(t2+1)/2+(a[i]-a[i-1]-t1-t2-1)*v-b[i];
        //cout<<"L: "<<l<<' '<<r<<endl;
    }
    r+=(b[m]+b[m]+n-a[m])*(n-a[m]+1)/2;
    if (b[m]>=n-a[m]) l+=(b[m]+b[m]-n+a[m])*(n-a[m]+1)/2;
    else l+=(b[m])*(b[m]+1)/2;

    //cout<<"L: "<<l<<' '<<r<<endl;
    if (T<=r&&T>=l) {
        cout<<"Yes"<<endl;
        return 0;
    }
    cout<<"No"<<endl;
}

猜你喜欢

转载自blog.csdn.net/z591826160/article/details/84205635