luogu P10134 [USACO24JAN] Cowmpetency S
一道好题,让我加强了对拍与细节的意识。
思路
对于 \(Q\) 对数 \((x,y)\),可以看作有两个限制:
-
\(\max\{c_{1} ... c_{x}\}=\max\{c_{1} ... c_{y-1}\}\)
-
\(\max\{c_{1} ... c_{x}\} < c_{y}\)
也就是说要构造一个字典序最小的序列,使得给定的这些条件全部满足。
首先对于第一个条件,如果不满足,因为我们想到得到的是字典序最小的序列,所以就考虑将 \(c_{i} ... c_{x}\) 中下标最大的待定值改为 \(\max\{c_{1} ... c_{y-1}\}\),如果没有就无解。
对于第二个条件,如果不满足,那么如果 \(c_{y}\) 待定,就修改即可,否则无解。
我们需要先考虑第一个条件,因为第一个条件会改变第二个条件需要用到的 \(\max\{c_{1} ... c_{x}\}\)。
然后由于我们需要字典序最小,所以我们将数对按照 \(x\) 排序,这样我们对于 \(c_{i}(i\le x)\) 的修改可以被后面的数对使用,到后面可以避免一定的修改。这是这样做的意义,略过正确性证明,读者可以自己思考这样做的正确性。
最后判断再一边所有的条件是否符合,以及是否所有的 \(c\) 中元素都小于 \(C\)。
Code
#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
using namespace std;
const int N=1e5+5;
struct node {
int l,r,maxn,lz;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define maxn(x) tr[x].maxn
#define lz(x) tr[x].lz
};
int c[N],go[N];
pair<int,int> l[N];
bool st[N];
int tt;
int n,q,C;
struct segment_tree {
node tr[N*4];
void pu(int x) {maxn(x)=max(maxn(x*2),maxn(x*2+1));}
void build(int x,int l,int r) {
l(x)=l,r(x)=r;
if(l==r) {
maxn(x)=c[l];
return;
}
int mid=l+r>>1;
build(x*2,l,mid),build(x*2+1,mid+1,r);
pu(x);
}
void change(int x,int pl,int k) {
int l=l(x),r=r(x);
if(l==r&&l==pl) {
maxn(x)=k;
return;
}
int mid=l+r>>1;
if(pl<=mid) change(x*2,pl,k);
else change(x*2+1,pl,k);
pu(x);
}
int qry(int x,int ll,int rr) {
if(ll>rr) return -1;
int l=l(x),r=r(x);
if(l>=ll&&r<=rr) return maxn(x);
int mid=l+r>>1,maxn=-1;
if(mid>=ll) maxn=max(maxn,qry(x*2,ll,rr));
if(mid<rr) maxn=max(maxn,qry(x*2+1,ll,rr));
pu(x);
return maxn;
}
}tree;
signed main() {
// freopen("A.out","w",stdout);
cin>>tt;
while(tt--) {
bool fd=0;
for(int i=1;i<=n;i++) c[i]=go[i]=st[i]=0;
for(int i=1;i<=q;i++) l[i]={0,0};
cin>>n>>q>>C;
for(int i=1;i<=n;i++) {
cin>>c[i];
if(!c[i]) {
go[i]=i;
}
else go[i]=go[i-1],st[i]=1;
}
for(int i=1;i<=q;i++) cin>>l[i].x>>l[i].y;
tree.build(1,1,n);
sort(l+1,l+1+q);
for(int i=1;i<=q;i++) {
if(max(tree.qry(1,1,l[i].x),(int)1)<max((int)1,tree.qry(1,1,l[i].y-1))) {
// cout<<"&&&&"<<i<<endl;
int tmp=max((int)1,tree.qry(1,1,l[i].y-1));
if(!go[l[i].x]) {
// cout<<"!!"<<endl;
fd=1;
break;
}
tree.change(1,go[l[i].x],tmp);
c[go[l[i].x]]=tmp;
}
if(st[l[i].y]) {
if(c[l[i].y]<=max((int)1,tree.qry(1,1,l[i].x))) {
// cout<<"??"<<endl;
fd=1;
break;
}
}
else if(c[l[i].y]<=max((int)1,tree.qry(1,1,l[i].x))) {
int tmp=max(tree.qry(1,1,l[i].x),(int)1)+1;
if(tmp>C) {
// cout<<"@@"<<endl;
fd=1;
break;
}
tree.change(1,l[i].y,tmp);
c[l[i].y]=tmp;
}
}
if(fd) {
puts("-1");
continue;
}
// for(int i=1;i<=n;i++) cout<<c[i]<<' ';
// cout<<endl;
for(int i=1;i<=q;i++) {
if(c[l[i].y]<=max((int)1,tree.qry(1,1,l[i].x))) {
// cout<<"**"<<endl;
fd=1;
break;
}
if(max((int)1,tree.qry(1,1,l[i].x))<max((int)1,tree.qry(1,1,l[i].y-1))) {
// cout<<"(("<<endl;
fd=1;
break;
}
}
for(int i=1;i<=n;i++) if(c[i]>C) {
// cout<<"##"<<endl;
fd=1;
break;
}
if(fd) {
puts("-1");
continue;
}
for(int i=1;i<=n;i++) if(c[i]) cout<<c[i]<<' '; else cout<<"1 ";
puts("");
}
return 0;
}

浙公网安备 33010602011771号