Codeforces Round #210 (Div. 1) A. Levko and Array Recovery (构造)

原题地址:http://codeforces.com/contest/360/problem/A
题意:有两种操作,第一种操作是将l到r之间的数加d;第二种操作是求l到r间的最大值
现在已知操作的情况,问你原始的序列是怎么样的。是否存在。存在输出YES并输出序列,否则输出NO。

思路:这题一开始真的毫无头绪.看来题解才知道这个构造太巧妙了.我们反方思考,要求初始的序列,那么我们可以先给初始的a序列赋值INF,然后对于m次操作,倒着进行,如果原来是区间加法操作,那么就减去相应的值,如果是求最大值的操作,就将比这个值大的位置改成当前最大值.

当处理完之后,在正着验证就行了.

注意一下d可以取负值就行了.

#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <cctype>
#define eps 1e-8
#define INF 1e9
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
int n, m;
int a[5005];
struct node {
    int flag, l, r, a;
} e[5005];

int b[5005];
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) a[i] = INF;
    for(int i = 1; i <= m; i++) {
        scanf("%d%d%d%d", &e[i].flag, &e[i].l, &e[i].r, &e[i].a);
    }
    for(int i = m; i >= 1; i--) {
        int flag = e[i].flag;
        if(flag == 1) {
            for(int j = e[i].l; j <= e[i].r; j++) {
                a[j] -= e[i].a;
                if(a[j] > INF) a[j] = INF; //因为d可能是负数,导致a的数据不合法
            }
        } else {
            for(int j = e[i].l; j <= e[i].r; j++) {
                a[j] = min(e[i].a, a[j]);//取小的那一个
            }
        }
        int flag = 1;
        for(int i = 1; i <= n; i++) b[i] = a[i];
        for(int i = 1; i <= m; i++) {
            if(e[i].flag == 1) {
                for(int j = e[i].l; j <= e[i].r; j++) {
                    b[j] += e[i].a;
                }
            } else {
                int MAX = -INF;//注意是-INF
                for(int j = e[i].l; j <= e[i].r; j++) {
                    MAX = max(MAX, b[j]);
                }
                if(MAX != e[i].a) flag = 0;
            }
        }
        if(flag) {
            printf("YES\n");
            for(int i = 1; i <= n; i++) printf("%d ", a[i]);
        } else printf("NO\n");
        return 0;
    }

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81515951