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;
}
posted @ 2024-10-04 22:05  PM_pro  阅读(19)  评论(0)    收藏  举报