题解:CF2116D
显然我们有一个想法就是把 \(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;
}

浙公网安备 33010602011771号