题目链接
题意:给定长度为 n 的数组a, 有 m 个限制条件,要求构造出这个数组
限制条件: ti li ri
条件一 :ti == 1 , 在数组区间为 [li, ri] 是非递减的
条件二 :ti == 0, 在数组区间为 [li, ri] 不是非递减的
这样的C题对于我来说,体验还是很棒的,可是我没打
思路:首先,对于非递减, 序列 5 5 5 5 5, 是符合的
所以, 在这个题目里,我先把 ti == 1 的限制条件处理掉
对于一些相交的是可以合并为一个区间的(想一下就知道了)
这样,可能会得到一些区间是要满足限制一的,在限制二下, 按照贪心, 我们可以把这些区间从大到小构造
最后, 限制二是否会起冲突
#include <bits/stdc++.h>
const int maxn = 1500;
using namespace std;
typedef long long ll;
struct note{
int l, r;
} a[maxn];
int vis[maxn], ans[maxn], n, m;
//vis 标记数组
int main()
{
int cnt = 0, col = 0;
scanf("%d%d", &n, &m);
while(m--){
int op;
scanf("%d%d%d", &op, &a[cnt].l, &a[cnt].r);
if(op == 1){ //处理区间 标记 有可能会有合并
int t = ++col;
int qian = vis[a[cnt].l], hou = vis[a[cnt].r];
t = (qian == 0) ? t : qian; //如果和前面的区间有交集,用前面区间的标记去覆盖
for (int i = a[cnt].l; i<=a[cnt].r; i++) //标记
vis[i] = t;
for (int i = a[cnt].r + 1; i<=n; i++){ //覆盖后面的区间
if(hou && hou == vis[i])
vis[i] = t;
else
break;
}
}
else
cnt++; //先保存,等下处理
}
ans[0] = 1500; //取个较大的数
for (int i = 1; i<=n; i++){
if(vis[i] != vis[i-1]){
ans[i] = ans[i - 1] - 1;
}
else{
if(vis[i] == 0)
ans[i] = ans[i - 1] - 1;
else //限制一,在一个非递减子序列里
ans[i] = ans[i - 1];
}
}
for (int i = 0; i < cnt; i++){
/*
没冲突情况
1 区间里,有两个不同的非递减子序列
2 区间里,至少有一个没被标记的点
*/
int t = vis[a[i].l], mark = 0;
for (int j = a[i].l + 1; j <= a[i].r; j++){
if(vis[j] != t){
mark = 1;
break;
}
}
if(!mark && t){ //冲突
printf("NO
");
return 0;
}
}
printf("YES
");
for (int i = 1; i<=n; i++){
printf("%d ", ans[i]);
}
printf("
");
return 0;
}