题解:【CF226D】The table

题目链接

调整构造。

发现 \(n\)\(m\) 较小只有 \(100\),因此可以考虑尝试进行修改从而不断逼近答案。

容易发现如果将某一行或列上的数字翻转,那么得到的新的和一定与原来的和异号,因此答案一定有解。在每次操作中,我们寻找是否有行或列和为负值,如果有就翻转。这样操作答案一定是单增的。

单次操作的时间复杂度为 \(O(n)\),一次操作至少能将答案增加 \(2\),又有 \(\lvert a_{i,j} \rvert \le 100\),所以整个矩阵中的值最小为 \(-100^3\),总的操作次数不会超过 \(500000\) 次,事实证明很难跑满。

特别的,在这种自适应的调整中会出现“撤销”的操作,即将同一行或列翻转两次,此时相当于不进行该操作,需要删掉。

\(Code\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read()
{
	int s=0,w=1;
	char c=getchar();
	while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
	while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
	return s*w;
}

namespace LgxTpre
{
	static const int MAX=110;
	static const int mod=998244353;
	static const int INF=200707070707;
	
	int n,m;
	int a[MAX][MAX];
	
	int rsum[MAX],csum[MAX];
	set<int> rop,cop;
	inline int check()
	{
		for(int i=1;i<=n;++i)
			if(rsum[i]<0)
				return i;
		for(int i=1;i<=m;++i)
			if(csum[i]<0) 
				return i+n;
		return -1;
	}
	inline void print()
	{
		for(int i=1;i<=n;++i,puts(""))
			for(int j=1;j<=m;++j)
				cout<<a[i][j]<<" ";
		for(int i=1;i<=n;++i)
			cout<<rsum[i]<<" ";
		cout<<endl;
		for(int i=1;i<=m;++i)
			cout<<csum[i]<<" ";
		cout<<endl;
		getchar();
	}
	inline void solve()
	{
		while(1)
		{
			int p=check();
			if(p==-1) break;
			if(p<=n)
			{
				if(rop.find(p)!=rop.end()) rop.erase(p);
				else rop.insert(p);
				for(int i=1;i<=m;++i)
					rsum[p]-=a[p][i],csum[i]-=a[p][i],
					a[p][i]=-a[p][i],
					rsum[p]+=a[p][i],csum[i]+=a[p][i];					
			}
			if(p>n)
			{
				p-=n;
				if(cop.find(p)!=cop.end()) cop.erase(p);
				else cop.insert(p);
				for(int i=1;i<=n;++i)
					csum[p]-=a[i][p],rsum[i]-=a[i][p],
					a[i][p]=-a[i][p],
					csum[p]+=a[i][p],rsum[i]+=a[i][p];
			}
		}
		return;
	}
	
	inline void lmy_forever()
	{
		n=read(),m=read();
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				a[i][j]=read(),
				rsum[i]+=a[i][j],csum[j]+=a[i][j];
		solve();
		cout<<rop.size()<<" ";
		for(auto it=rop.cbegin();it!=rop.cend();++it)
			cout<<*it<<" ";
		cout<<endl;
		cout<<cop.size()<<" ";
		for(auto it=cop.cbegin();it!=cop.cend();++it)
			cout<<*it<<" ";
		return;
	}
}

signed main()
{
	LgxTpre::lmy_forever();
	return (0-0);
}
posted @ 2023-01-29 11:17  LgxTpre  阅读(27)  评论(0编辑  收藏  举报