P9786 题解
因为每一列构成排列,如果给
暴力枚举
现在只需要一种快速修改的方法。对于指令,
#include <bits/stdc++.h>
using namespace std;
constexpr int N=3e5+5;
int n,m,s;
struct Op{
int a,b,t;
};
vector<int> x[N],pos[N],fa[N],val[N];
// pos[i][j]: i 在第 j 列的第几行
vector<Op> op[N];
int z[N],crtcnt;
void upd(int i){
if(z[i]==1) return;
int p=pos[z[i]-1][i];
// val[p][i]: 0->1
val[p][i]=1;
if(n==1){
++crtcnt;
return;
}
int u{fa[p][i]};
for(;;u=fa[p][u]){
if(val[p][u]) break;
auto t=op[p][u-n];
if(t.t==1) val[p][u]=(val[p][t.a]&&val[p][t.b]);
else val[p][u]=(val[p][t.a]||val[p][t.b]);
if(!val[p][u]) break;
if(u==2*n-1){
++crtcnt;
break;
}
}
// printf("crtcnt=%d\n",crtcnt);
}
signed main(){
scanf("%d%d%d",&n,&m,&s);
for(int i{1};i<=m;++i){
x[i].resize(n+3);
op[i].resize(n+3);
pos[i].resize(n+3);
fa[i].resize(n*2+5);
val[i].resize(n*2+5);
for(int j{1};j<=2*n-1;++j){
val[i][j]=0;
}
}
for(int i{1};i<=m;++i){
for(int j{1};j<=n-1;++j){
int a,b,t;scanf("%d%d%d",&a,&b,&t);
op[i][j]={a,b,t};
fa[i][a]=fa[i][b]=n+j;
}
}
for(int i{1};i<=m;++i){
for(int j{1};j<=n;++j){
scanf("%d",&x[i][j]);
++x[i][j];
pos[x[i][j]][j]=i;
}
}
for(int i{1};i<=n;++i) z[i]=1;
for(int i{1};i<=n;++i){
if(crtcnt==s) break;
for(;;++z[i],upd(i)){
if(crtcnt==s){
i=n+1;
break;
}
if(z[i]==m+1) break;
}
}
for(int i{1};i<=n;++i){
printf("%d%c",z[i]-1," \n"[i==n]);
}
return 0;
}