【树】【dfs】【模拟】I Like Matrix Forever!
对一个 n ∗ m 的零矩阵 A 进行 q 次操作:
• 1 i j:将 Ai,j 取反;
• 2 i:将矩阵 A 第 i 行的所有元素全部取反;
• 3 j:将矩阵 A 第 j 列的所有元素全部取反;
• 4 k:将矩阵 A 还原为第 k 次操作之后的状态。
进行每一次操作之后,询问当前矩阵所有元素的和。
第一行包含三个整数 n,m 和 q。
之后 q 行每行包含两个或三个整数,表示一次操作的所有参数。
共 q 行每行包含一个整数 ans,表示当前矩阵所有元素的和。
2 2 4
2 1
1 1 2
4 1
3 2
2
1
2
2
可以看成一个树,如图:
新的操作与上一个操作连接起来,然后模拟三种操作,dfs就可以了
必须要用快读和快输(否则会TLE)
#include<cstdio>
#include<iostream>
using namespace std;
int N,M,m[1005][1005],t,q,h[100005],ans[100005],sum,l[100005],x[100005],y[100005];
int read()
{
int x=0,flag=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*flag;
}//快读
void write(int x)
{
if(x<0) {x=-x;putchar('-');}
if(x>9) write(x/10);
putchar(x%10+48);
return;
}//快输
struct node
{
int to,from;
}w[100001];
void link(int x,int y)
{w[++t]=(node){y,h[x]}; h[x]=t;}
void dfs(int dep)
{
if (l[dep]==1) {
sum+=1-(m[x[dep]][y[dep]]<<1);
m[x[dep]][y[dep]]=!m[x[dep]][y[dep]];
}
if (l[dep]==2) {
for (int i=1; i<=M; ++i)
{
sum+=1-(m[x[dep]][i]<<1);
m[x[dep]][i]=!m[x[dep]][i];
}
}
if (l[dep]==3) {
for (int i=1; i<=N; ++i)
{
sum+=1-(m[i][x[dep]]<<1);
m[i][x[dep]]=!m[i][x[dep]];
}
}//模拟
ans[dep]+=sum;
for (int i=h[dep];i;i=w[i].from) dfs(w[i].to);//继续往下搜
if (l[dep]==1) {
sum+=1-(m[x[dep]][y[dep]]<<1);
m[x[dep]][y[dep]]=!m[x[dep]][y[dep]];
}
if (l[dep]==2) {
for (int i=1; i<=M; ++i)
{
sum+=1-(m[x[dep]][i]<<1);
m[x[dep]][i]=!m[x[dep]][i];
}
}
if (l[dep]==3) {
for (int i=1; i<=N; ++i)
{
sum+=1-(m[i][x[dep]]<<1);
m[i][x[dep]]=!m[i][x[dep]];
}
}//还原回去
}
int main()
{
N=read(); M=read(); q=read();
for (int i=1; i<=q; ++i)
{
l[i]=read(); x[i]=read();
if (l[i]==1) y[i]=read();
if (l[i]!=4) link(i-1,i);//连接上一点的操作
else link(x[i],i);//连接回到哪个点
}
dfs(0);
for (int i=1; i<=q; ++i)
write(ans[i]),putchar(10);
}