I Like Matrix Forever!
题目大意:
有一个01矩阵,有一些操作:反转一个位置的数,反转一行的数,反转一列的数,回到第i次操作,每一次操作还要输出1的个数
原题:
题目描述
对一个 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
说明
对于 30% 的数据:n, m ≤ 300,q ≤ 1000
对于 60% 的数据:n, m ≤ 1000,q ≤ 5000
对于 100% 的数据:n, m ≤ 1000,q ≤ 100000
解题思路:
实际上可以把它看作一棵树,每一次操作为一个节点,操作四为一个分支,然后每次返回是再翻一遍
然后模拟即可
代码:
#include<cstdio>
using namespace std;
int n,m,q,w,sum,l[100005],x[100005],y[100005],head[100005],ans[100005],a[1005][1005];
struct rec
{int to,next;
}e[100005];
int read()//快读
{char xx=getchar();int d=1,ll=0;while (xx<'0'||xx>'9') {if (xx=='-') d=-1; xx=getchar();}while (xx>='0'&&xx<='9') ll=(ll<<3)+(ll<<1)+xx-48,xx=getchar();return ll*d;
}
void writ(int c) {if (c>9) writ(c/10); putchar(c%10+48); return;}
void write(int s) {s<0?putchar(45),writ(-s):writ(s); return;}
void lj(int xx,int yy)//连接
{e[++w].to=yy;e[w].next=head[xx];head[xx]=w;
}
void dfs(int dep)//深搜
{if (l[dep]==1)//模拟{sum+=1-(a[x[dep]][y[dep]]<<1);//答案随这个数改变而改变a[x[dep]][y[dep]]^=1;//取反}if (l[dep]==2){for (int i=1;i<=m;++i){sum+=1-(a[x[dep]][i]<<1);a[x[dep]][i]^=1;}}if (l[dep]==3){for (int i=1;i<=n;++i){sum+=1-(a[i][x[dep]]<<1);a[i][x[dep]]^=1;}}ans[dep]=sum;for (int i=head[dep];i;i=e[i].next) dfs(e[i].to);//深搜if (l[dep]==1)//翻回来{sum+=1-(a[x[dep]][y[dep]]<<1);a[x[dep]][y[dep]]^=1;}if (l[dep]==2){for (int i=1;i<=m;++i){sum+=1-(a[x[dep]][i]<<1);a[x[dep]][i]^=1;}}if (l[dep]==3){for (int i=1;i<=n;++i){sum+=1-(a[i][x[dep]]<<1);a[i][x[dep]]^=1;}}return;
}
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) lj(i-1,i);//分支else lj(x[i],i);}dfs(0);for (int i=1;i<=q;++i) write(ans[i]),putchar(10);//输出
}