题解:CF2116D

link

显然我们有一个想法就是把 \(b\) 倒序还原每个操作,进而得到 \(a\),但这样会出现一些无法填的空位(笔者赛时就这样甜筒被创飞了),并做不了。

我们转而考虑构造一个"必要"的 \(a\),即使得每次操作时 \(\min\{c_{x_i},c_{y_i}\}\ge c_{z_i}\)。我们仍然是倒序还原每个操作,令 \(t\) 为原来的 \(b_{z_i}\),然后给 \(b_{z_i}\) 随便置一个 \(\le 0\) 的数。接下来分别 \(b_{x_i}\gets\max\{b_{x_i},t\}\)\(b_{y_i}\gets\max\{b_{y_i},t\}\),显然这两个操作是必要的,这也是为什么我们可以给空位随便置数,因为前面的操作会为它确定值。

还原所有操作后,我们正序执行一遍所有操作,验证是否会还原成给定的 \(b\) 即可,总时间复杂度为 \(O(n+q)\)

参考资料:甜筒的神秘讲题,CF官方题解

Code:

#include<iostream>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
const int maxn=3e5+5;
int a1[maxn],ans[maxn],ab[maxn],ax[maxn],ay[maxn],az[maxn];
int main(){
	int it;
	cin>>it;
	while(it--){
		int in,iq;
		scanf("%d %d",&in,&iq);
		rep(v1,1,in){
			scanf("%d",a1+v1);
			ab[v1]=a1[v1];
		}
		rep(v1,1,iq){
			scanf("%d %d %d",ax+v1,ay+v1,az+v1);
		}
		bool flag=true;
		per(v1,iq,1){
			int tar=a1[az[v1]];
			a1[az[v1]]=0;
			a1[ax[v1]]=max(a1[ax[v1]],tar);
			a1[ay[v1]]=max(a1[ay[v1]],tar);
		}
		rep(v1,1,in)ans[v1]=a1[v1];
		rep(v1,1,iq)a1[az[v1]]=min(a1[ax[v1]],a1[ay[v1]]);
		rep(v1,1,in){
			if(a1[v1]!=ab[v1]){
				flag=false;
				break;
			}
		}
		if(flag){
			rep(v1,1,in)printf("%d%c",ans[v1],v1==in?'\n':' ');
		}
		else printf("-1\n");
	}
	return 0;
}
posted @ 2025-06-04 19:10  FugiPig  阅读(18)  评论(0)    收藏  举报