题解:CF2162H Beautiful Problem
思路
若一个区间被另一个区间完全包含,则这个区间没有任何作用,我们可以去掉它,这是不难发现的。
首先发现对于一个
我们定义一个所有数都
然后对于一个位置,有
我们先考虑没有第
假设现在有
那么当且仅当
那么现在加上类型
所以说,我们希望在
但是你发现有可能
然后直接用上面的方法对于每个
代码
#include<bits/stdc++.h>
#define int long long
#define N 2005
#define mod 998244353
#define pii pair<int,int>
#define x first
#define y second
#define pct __builtin_popcount
#define mpi make_pair
#define inf 2e18
using namespace std;
int T=1,n,m,cnt,a[N],f[N][N][2];
pii b[N];
bool st[N];
void solve(int cs){
if(!cs)return;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
st[i]=0;
}
for(int i=1;i<=m;i++){
cin>>b[i].x>>b[i].y;
}
sort(b+1,b+m+1);
cnt=0;
int mx=0;
for(int i=1;i<=m;i++){
if(mx>=b[i].y)continue;
mx=max(mx,b[i].y);
b[++cnt]=b[i];
}
m=cnt;
int free=0;
for(int i=1;i<=m;i++){
for(int j=b[i].x;j<=b[i].y;j++){
st[j]=1;
}
}
for(int i=1;i<=n;i++){
if(!st[i])free++;
}
for(int j=0;j<=n;j++){
f[1][j][0]=f[1][j][1]=-inf;
}
f[1][0][0]=b[1].y-b[1].x+1;
f[1][b[1].y-b[1].x+1][1]=0;
for(int i=2;i<=m;i++){
int len=b[i].y-b[i].x+1;
int cap=0;
if(b[i-1].y>=b[i].x)cap=b[i-1].y-b[i].x+1;
for(int j=0;j<=n;j++){
f[i][j][0]=f[i][j][1]=-inf;
}
for(int j=0;j<=n;j++){
int &v0=f[i][j][0],&v1=f[i][j][1];
v0=max(v0,f[i-1][j][0]+len-cap);
if(j+cap<=n)v0=max(v0,f[i-1][j+cap][1]+len-cap);
if(j>=len-cap)v1=max(v1,f[i-1][j-(len-cap)][0]-cap);
if(j>=len-cap)v1=max(v1,f[i-1][j-(len-cap)][1]);
}
}
for(int x=1;x<=n;x++){
int s=0,b=0;
for(int i=1;i<=n;i++){
if(a[i]<x)s++;
if(a[i]>x)b++;
}
bool flag=0;
for(int i=0;i<=n;i++){
int t1=max(0ll,s-i),t2=max(0ll,b-max(f[m][i][0],f[m][i][1]));
if(t1+t2<=free){
flag=1;
break;
}
}
cout<<flag;
}
cout<<'\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>T;
// init(1e5);
for(int cs=1;cs<=T;cs++){
solve(cs);
}
// cerr<<clock()*1.0/CLOCKS_PER_SEC<<'\n';
return 0;
}