CF1187C Vasya and array(Vasya和数组)(模拟)
Vasya has an array a1,a2,…,an.
Vasya有一个数组,a1,a2,...,an
You don't know this array, but he told you m facts about this array. The i-th fact is a triple of numbers ti, li and ri (0≤ti≤1,1≤li<ri≤n) and it means:
这个数组对于你来说不是已知的,但是他告诉你m个关于这个数组的消息。第i个消息是一个包含三个数的数对。
这意味着:
if ti=1 then subbarray ali,ali+1,…,ari is sorted in non-decreasing order;
如果ti=1,那么这个子数列ali,ali+1..,ari是以非递减顺序排好序的
if ti=0 then subbarray ali,ali+1,…,ari is not sorted in non-decreasing order.
如果ti=0,这个子序列就是没有以非递减顺序排好序的。
A subarray is not sorted if there is at least one pair of consecutive elements in this subarray such that the former is greater than the latter.
For example if a=[2,1,1,3,2] then he could give you three facts: t1=1,l1=2,r1=4 (the subarray [a2,a3,a4]=[1,1,3] is sorted), t2=0,l2=4,r2=5 (the subarray [a4,a5]=[3,2] is not sorted), and t3=0,l3=3,r3=5 (the subarray [a3,a5]=[1,3,2] is not sorted).
一个子数列没有被排序的话,当数列中有至少一对连续元素使得前一个大于后一个时成立。比如说……
You don't know the array a. Find any array which satisfies all the given facts.
你不知道这个数列a,找到任何一个数列使得给定的消息都可以被满足。
Input
The first line contains two integers n and m (2≤n≤1000,1≤m≤1000).
第一行包含两个整数n,m
Each of the next m lines contains three integers ti, li and ri (0≤ti≤1,1≤li<ri≤n).
接下来的m行包含三个整数
If ti=1 then subbarray ali,ali+1,…,ari is sorted. Otherwise (if ti=0) subbarray ali,ali+1,…,ari is not sorted.
如果ti=1,那么子数列ali...已经排好序(非递减),否则就是没排好序。
Output
If there is no array that satisfies these facts in only line print NO (in any letter case).
如果这里不存在任何数列满足条件,只需输出No
If there is a solution, print YES (in any letter case). In second line print n integers a1,a2,…,an (1≤ai≤109) — the array a, satisfying all the given facts. If there are multiple satisfying arrays you can print any of them.
如果存在解决方案,那么输出YES,第二行输出任意一个可行的解决方案。
Examples
inputCopy
7 4
1 1 3
1 2 5
0 5 6
1 6 7
outputCopy
YES
1 2 2 3 5 4 4
inputCopy
4 2
1 1 4
0 2 3
outputCopy
NO
这个题的解答分两部分。
第一种是如何判断NO:当1式区间和0式区间存在矛盾时自然会无解。什么时候存在矛盾呢?题设所说,1代表非递减,0代表非非递减,(无论什么顺序,总之不是非递减,乱序什么的也罢)。由于解题方便,这里不考虑乱序(可行但是较繁琐)。当一个应该是0式区间的范围内全体出现了1式区间的元素(也就是说这个0式区间内不存在0式元素,或者说这个区间被1式覆盖了),那么这个0式区间自然不可能是“非非递减”,因为它里边全是非递减序列。我们知道,非递减的临界是公差为0的序列,而非非递减的临界是一个子数列内至少存在一个元素使得本数列不是非递减顺序。那么,当0式区间内只要存在一个0式元素,这个区间段就可以被构造出来。
第二种是如何判断YES:如上文所述,如果不是NO就是YES。而如何把答案序列输出出来呢?可以设一个初始值,把非递减区间简单看做“无变化”,把递减区间简单看做逐步减一,得出来的就是答案。
怎么去标记所谓的0式区间和1式区间呢?一个最简单也是最暴力的办法就是构造一个标志数组,对每个元素进行标记。惊喜的是,本题数据范围出乎意料的小,这种方式确实可行。
所以有如下思路:
- 利用标记数组,首先标记1式区间
- 再对0式区间进行分析
- 得出结论,并输出答案
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
const int DEED = 50000;
ll imformation[DEED][3],mark[DEED];
int DETERMINATION()
{
ll n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
cin >> imformation[i][0] >> imformation[i][1] >> imformation[i][2];//用这种方式来储存信息
for (int i = 1; i <= m; i++)
{
if (imformation[i][0] == 1)
//对一式区间进行标记
for (int j = imformation[i][1]; j < imformation[i][2]; j++)
mark[j] = 1;
}
for (int i = 1; i <= m; i++)
{
bool sign = false;
if (imformation[i][0] == 0)
{
for (int j = imformation[i][1]; j < imformation[i][2]; j++)
{
if (mark[j] == 0)
{
sign = true;
break;//存在一个0式元素,全体成立
}
}
if (sign == false)
{
cout << "NO" << endl;
return 0;//否则GG
}
}
}
cout << "YES" << endl;
ll lim = n+1;
for (int i = 1; i <= n; i++)
if (mark[i-1] == 0)//由于这是从前往后构造,所谓的递增递减都是根据前一个元素“相对”出来的概念,所以要根据前一个元素的标志判断
{
lim -=1;
cout << lim << " ";
}
else
cout << lim << " ";
cout << endl;
return 0;
}