题目含义:给定一个长度为n的数列,给你m次操作 ,输入t,l,r ,如果t等于1的话说明l到r之间是不降序区间,t=0则相反,然后问你这所有询问是否有矛盾,如果无矛盾输入一组解。
思路:定义一个差分序列,原数组flag[i]代表i与i+1是否呈不降序,那么可以发现t等于1的时候每次操作就等价于将a[l]++和a[r]–,然后我们把所有前缀和累加起来,如果flag大于0则a[i]=true,将所有t=0的询问放到容器里面处理,判断是否矛盾等价于s[y-1]-s[x-1]==y-x,s数组表示的是前缀和,如果区间值等于他们的区间长度,那么必定满足整个区间是不降的,那么肯定不满足至少存在一个元素降序。然后是构造的方法,我们从n+2开始,为什么呢?如果小于n容易弄成负数,既然是不降那么我们直接能成相等就行了,然后我们可以发现,除了不降区间剩下的区间都是降区间,那么我们循环i,如果碰到flag[i-1]==true的时候直接–输出的值就行了。
ac代码:
#include<iostream>
#include<cstring>
#include<set>
#include<vector>
using namespace std;
const int N=1010;
const int M=10010;
typedef long long ll;
typedef pair<int,int> pii;
int n,m;
int flag[N];
int s[N];
vector<pii>query;
int main()
{
cin >> n >> m;
while(m--)
{
int t,l,r;
cin>>t>>l>>r;
if(t==1) flag[l]++,flag[r]--;
else query.push_back({
l,r});
}
for(int i=1;i<=n;i++)
{
flag[i]+=flag[i-1];
// s[i]=s[i-1]+flag[i];
}
for(int i=1;i<=n;i++)
flag[i]=flag[i]?true:false;
for(int i=1;i<=n;i++)
s[i]=s[i-1]+flag[i];
int f=true;
for(pii it:query)
{
int x=it.first;
int y=it.second;
if(s[y-1]-s[x-1]==(y-x))
{
f=false;
break;
}
}
if(!f)
puts("NO");
else
{
int res=n+2;
puts("YES");
cout<<res<<' ';
for(int i=2;i<=n;i++)
{
if(flag[i-1])
cout<<res<<' ';
else
cout<<--res<<' ';
}
cout<<endl;
}
return 0;
}