[CF226D]The table

89 篇文章 0 订阅

题目

传送门 to luogu

思路

朴实的思路:每次找一个和为负数的,并翻转。死循环?

不要害怕死循环。注意到每次翻转时,矩阵内所有元素的和都在变大。一次至少变大 2 2 2 。于是复杂度 O [ n m a ( n + m ) ] \mathcal O[nma(n+m)] O[nma(n+m)] ,这是最坏情况。应该是卡不到。

代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
inline int readint(){
	int a = 0; char c = getchar(), f = 1;
	for(; c<'0'||c>'9'; c=getchar())
		if(c == '-') f = -f;
	for(; '0'<=c&&c<='9'; c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}
template < typename T >
void getMax(T&a,const T&b){if(a<b)a=b;}
template < typename T >
void getMin(T&a,const T&b){if(b<a)a=b;}

const int MaxN = 105;
int row[MaxN], col[MaxN], a[MaxN][MaxN];
int ansr[MaxN], ansc[MaxN], n, m;

int main(){
	n = readint(), m = readint();
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j){
			a[i][j] = readint();
			row[i] += a[i][j];
			col[j] += a[i][j];
		}
	while(true){
		bool ok = true;
		for(int i=1; i<=n; ++i)
			if(row[i] < 0){
				ok = false;
				for(int j=1; j<=m; ++j){
					col[j] -= a[i][j]<<1;
					a[i][j] -= a[i][j]<<1;
				}
				row[i] -= row[i]<<1;
				ansr[i] ^= 1;
			}
		for(int j=1; j<=m; ++j)
			if(col[j] < 0){
				ok = false;
				for(int i=1; i<=n; ++i){
					row[i] -= a[i][j]<<1;
					a[i][j] -= a[i][j]<<1;
				}
				col[j] -= col[j]<<1;
				ansc[j] ^= 1;
			}
		if(ok) break;
	}
	int R = 0, C = 0;
	for(int i=1; i<=n; ++i)
		R += ansr[i];
	for(int i=1; i<=m; ++i)
		C += ansc[i];
	printf("%d",R);
	for(int i=1; i<=n; ++i)
		if(ansr[i]) printf(" %d",i);
	printf("\n%d",C);
	for(int i=1; i<=m; ++i)
		if(ansc[i]) printf(" %d",i);
	putchar('\n'); return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值