HDU 6860 Fluctuation Limit(2020杭电多校暑期训练第八场)

Fluctuation Limit
Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 268 Accepted Submission(s): 123
Special Judge

Problem Description
It is preferrable to read the pdf statment.

Cuber QQ has signed up for a gambling game, that challenges him to predict the stock price of Quber CC Limited, for the next following n days. He shall make his prediction by filling a table with n intervals, the i-th of which is the predicted interval [li,ri] at the i-th day. If all n prices lie in the corresponding interval, Cuber QQ will win 1 million dollars. Otherwise, he will not earn a single penny.

As is well known, the stock price has a fluctuation limit. For simplicity, we assume the limit up and the limit down are both k, which is an integer. That means, if the stock price at the i-th day is x, the price at the i+1-th day is at most x+k and at least x−k.

Cuber QQ wants to know whether it is possible to manipulate the stock price, without breaking the limitation above of course, so that he can have the 1 million dollars. Since his table has already been submitted, he cannot modify his predicted intervals any more. It has to be done secretly behind the scenes, and smartly cover it up so that no one will notice.

Input
The input starts with an integer T (1≤T≤105), denoting the number of test cases.

For each test case, the first line contains two space-separated integers n and k (2≤n≤105, 0≤k≤109), where n is the number of days and k is the fluctuation limit.

The i-th line of the next n lines contains two space-separated integers li and ri (0≤li≤ri≤109), which is Cuber QQ’s predicted interval in the i-th day. A prediction is believed to be correct if the stock price i-th day lies between li and ri, inclusive.

It is guaranteed that the sum of all n does not exceed 106.

Output
For each test case, first output a single line YES or NO, that states whether Cuber QQ will win the 1 million price.

If YES, in the next line, output a possible price series, a1,a2,…,an, where li≤ai≤ri (1≤i≤n) and |ai−ai+1|≤k (1≤i≤n−1). The integers should be separated with space.

Sample Input

2
3 1
1 6
2 5
3 6
2 3
1 5
10 50

Sample Output

YES
2 3 3
NO

题意:

给你一个n和k,给你n个价格范围l,r,问最后没组价格的上下浮动能不能不超过k。若可以,那么输出YES并输出他的价格序列;否则出NO。

题解:

我们可以根据给定的第一个区间,推断第二个区间满足第二个条件的范围,也就是[l1 - x, r1 + x],然后再让这个区间和[l2,r2]区间取并集,那么得到的区间中的任何一个数字都是合法区间
Code1:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include <fstream>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const double pi=acos(-1.0),eps=1e-8;
const ll mod =  998244353;
const int maxn=1e5+5;
vector<int>v;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        v.clear();
        int n,k;
        scanf("%d %d",&n,&k);
        int l,r;
        scanf("%d %d",&l,&r);
        v.push_back(l);
        int flag=1;
        for(int i=1; i<n; i++)
        {
            int la,ra;
            scanf("%d %d",&la,&ra);
            if(!flag)
                continue;
            l-=k;
            r+=k;
            if(l<=ra&&r>=la)
            {
                l=max(l,la);//取并集
                r=min(r,ra);//取并集
                v.push_back(l);
            }
            else
            {
                flag=0;
            }
        }
        if(flag)
        {
            printf("YES\n");
            for(int i=n-2; i>=0; i--)
            {
                if(v[i+1]-v[i]>k)
                    v[i]=v[i+1]-k;
            }
            for(int i=0; i<n; i++)
            {
                if(i==0)
                    printf("%d",v[i]);
                else
                    printf(" %d",v[i]);
            }
            printf("\n");
        }
        else
            printf("NO\n");
    }
    return 0;
}

如果 i 是在 [l,r] 范围内, 那么 i + 1 必须要在 [l−k,r + k] 范围内。
这是因为如果 i + 1 选了 范围外的值, i 就无解了。
这样可以从左往右, 把左边的约束带到右边.再从右往左做一遍.最后剩下的区间就是可行域.
Code2:

#include <bits/stdc++.h>
using namespace std;

const int N = 1E5 + 100;
int l[N], r[N];

int main()
{
    ios::sync_with_stdio(false);
    int q;
    cin >> q;
    while (q--)
    {
        int n, k;
        cin >> n >> k;
        for (int i = 1; i <= n; ++i)
        {
            cin >> l[i] >> r[i];
        }
        for (int i = 1; i < n; ++i)
        {
            l[i + 1] = max(l[i + 1], l[i] - k);
            r[i + 1] = min(r[i + 1], r[i] + k);
        }
//        printf("\n");
//        for(int i=1;i<=n;i++)
//        {
//            printf("%d %d\n",l[i],r[i]);
//        }
//        printf("\n");
        for (int i = n; i > 1; --i)
        {
            l[i - 1] = max(l[i - 1], l[i] - k);
            r[i - 1] = min(r[i - 1], r[i] + k);
        }
//        for(int i=1;i<=n;i++)
//        {
//            printf("%d %d\n",l[i],r[i]);
//        }
//        printf("\n");
        bool ok = true;
        for (int i = 1; i <= n; ++i)
        {
            if (l[i] > r[i])
            {
                ok = false;
            }
        }
        if (ok)
        {
            cout << "YES" << endl;
            for (int i = 1; i <= n; ++i)
            {
                if(i==1)
                    cout << l[i];
                else
                    cout<<" "<<l[i];
            }
            cout<<endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值