Slika
题意:
首先,题目有一个外衣,就是操作有版本的概念,他会进行存档和读档操作,但是我们知道,我们把操作建成一个树,他读档就是回到一个祖先,而对最终形态有影响的只有当前点到根的叠加操作。
那么我们就建一棵树,维护一个fa数组,最后不断跳祖先就知道了有效操作及顺序。
做法一:
用并查集维护当前行没染色的最右边的点。
我们把操作,逆序搞,因为后面染色的会覆盖前面染色的操作。
然后呢对于一段染过色的区间是不会被重复遍历的。
那么总的复杂度就是(
m
∗
n
+
n
∗
n
m*n+n*n
m∗n+n∗n)。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n,m) for(int i=n;i<=m;i++)
#define repp(i,n,m) for(int i=n;i>=m;i--)
int n,k,m;
char op[10];
int sa[100040];
int cnts=0,tot=0;
struct node{
int cl;
int x1,y1,x2,y2;
}z[100040];
queue<int>q;
int f[100050];
int fa[1010][1010];
int col[1004][1004];
int find(int x,int i){
if(x==fa[i][x])return x;
return fa[i][x]=find(fa[i][x],i);
}
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>k>>m;
int now=0;
for(int i=1;i<=m;i++){
cin>>op;
if(op[0]=='P'){
tot++;
cin>>z[tot].cl>>z[tot].x1>>z[tot].y1>>z[tot].x2>>z[tot].y2;
f[tot]=now;
now=tot;
}else if(op[0]=='S'){
cnts++;
sa[cnts]=now;
}else{
int a;
cin>>a;
now=sa[a];
}
}
for(int i=0;i<n+2;i++){
for(int j=0;j<n+2;j++)col[i][j]=1,fa[i][j]=j;
}
while(now){
int u=now;
for(int i=z[u].x1;i<=z[u].x2;i++){
int p;
if((i-z[u].x1)%2==0)p=find(z[u].y1,i);
else p=find(z[u].y1+1,i);
for(int j=p;j<=z[u].y2;j=find(j+2,i)){
fa[i][j]=j+2;
col[i][j]=z[u].cl;
}
}
now=f[now];
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)cout<<col[i][j]<<" ";
cout<<"\n";
}
return 0;
}
做法二: