【题目描述】
从前有个 n×m 的矩阵,初始时每个位置均为 0。你需要依次执行 q 个操作,每个操作会指定一行或一列,然后将该行或该列的所有元素全部赋为一个相同的值。 输出操作完成后的矩阵。
【输入格式】
从文件 matrix.in 中读入数据。 第一行包含三个整数 n,m,q,分别表示矩阵的大小和操作次数。 接下来 q 行,每行三个正整数 t,x,y,若 t = 1,则表示将第 x 行的所有元素赋为 y; 若 t = 2,则表示将第 x 列的所有元素赋为 y。
【输出格式】 输出到文件 matrix.out 中。 输出 n 行,每行 m 个由空格隔开的整数,表示操作完成后的矩阵。
【样例 1 输入】
3 3 3
1 1 3
2 2 1
1 2 2
【样例 1 输出】
3 1 3
2 2 2
0 1 0
【样例 2 输入】
5 3 5
1 1 1
1 3 1
1 5 1
2 1 1
2 3 1
【样例 2 输出】
1 1 1
1 0 1
1 1 1
1 0 1
1 1 1
注意:
n,m≤1000,n×m≤105,q≤106。 数据保证任一时刻矩阵中所有元素小于 2^31。
解题思路:
- 可以看到注意里的q的次数最多可达到10^6,蛮力法肯定是超时的,所以就得从减少操作次数做起。可以看到,如果在保持操作顺序不变的情况下,后面的的操作会替代掉前面的对同一行或者同一列的操作,所以我们可以从最后一次开始操作。
- 假设矩阵为s[n][m],输入的为t,x,y,弄个H[n]和L[m]表示对某一行或者某一列是否操作过,如果已经操作过(假设H[x])就跳过,没有就对这一行或者这一列赋值y,然后对H[x]或者L[x]赋值1,表示已经操作过。
- 注意::假如我们在正序操作时,第n个操作数对第一列赋值,第n+1个操作时对第一行操作,在倒序操作时,如果直接判断行列是否操作过而不去考虑对于的行或列元素是否已经赋值,则左上角那个数会被第n次操作覆盖掉而出错。所以记得判断对于行列里的元素是否已经赋值。
代码如下:
#includeusing namespace std; struct operators{ int t; int x; int y; }; int s[1005][1005]={0}; int h[1005]={0}; int l[1005]={0}; operators a[1000005]={0}; int main() { int m,n,q; cin>>m>>n>>q; for(int i=1;i<=q;i++) { cin>>a[i].t>>a[i].x>>a[i].y; //记录每次操作 } for(int i=q;i>=1;i--) //倒序开始操作 { if(a[i].t==1) //对行操作,如果行标志数组为1则跳过,防止重复赋值。 { if(h[a[i].x]==1) continue; else{ for(int j=1;j<=m;j++) { if(s[a[i].x][j]) continue; //判断是否某行某列是否已经赋过值,避免倒序操作对第i行和第i列操作覆盖掉(相对)左上角的值 else{ s[a[i].x][j]=a[i].y; } } h[a[i].x]=1; } } else { if(l[a[i].x]==1) continue; else{ for(int j=1;j<=m;j++) { if(s[j][a[i].x]) continue; else{ s[j][a[i].x]=a[i].y; } } l[a[i].x]=1; } } } for(int i=1;i<=n;i++) { cout<



