105. 七夕祭 / 混合基础知识

传送门

题目

七夕节因牛郎织女的传说而被扣上了「情人节」的帽子。

于是TYVJ今年举办了一次线下七夕祭。

Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩。

TYVJ七夕祭和11区的夏祭的形式很像。

矩形的祭典会场由N排M列共计N×M个摊点组成。

虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧、苹果糖、棉花糖、射的屋……什么的。

Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊点数也一样多。

不过zhq告诉Vani,摊点已经随意布置完毕了,如果想满足cl的要求,唯一的调整方式就是交换两个相邻的摊点。

两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置上。

由于zhq率领的TYVJ开发小组成功地扭曲了空间,每一行或每一列的第一个位置和最后一个位置也算作相邻。

现在Vani想知道他的两个要求最多能满足多少个。

在此前提下,至少需要交换多少次摊点。

输入格式

第一行包含三个整数N和M和T,T表示cl对多少个摊点感兴趣。

接下来T行,每行两个整数x, y,表示cl对处在第x行第y列的摊点感兴趣。

输出格式

首先输出一个字符串。

如果能满足Vani的全部两个要求,输出both;

如果通过调整只能使得各行中cl感兴趣的摊点数一样多,输出row;

如果只能使各列中cl感兴趣的摊点数一样多,输出column;

如果均不能满足,输出impossible。

如果输出的字符串不是impossible, 接下来输出最小交换次数,与字符串之间用一个空格隔开。

数据范围

1≤N,M≤100000,
0≤T≤min(N∗M,100000),
1≤x≤N,
1≤y≤M

输入样例:
2 3 4
1 3
2 1
2 2
2 3

输出样例:
row 1

【题解】:想法有点受环形纸牌启发。
1.这题的横竖行是不会相互影响的,可以看成两边去计算。用t(要摆的摊位数)分别去和n,m取余,如果可以整除就存在满足的情况。
2.最小的移动数分开来求。结论是从中位数开始移动结果最小。
证明:
把每数的需求算出来以后,从接口处(0的地方)求前缀和sum,假设从k开始移动,那么移动次数为|sum【1】-sum【k】|+|sum【2】-sum【k】|+|sum【3】-sum【k】|+…可以知道当sum【k】是中位数的时候整个结果最小,所以排序之后取就好了。

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn=100004;
int hang[maxn],lie[maxn];
int sumh[maxn],suml[maxn];

int main() 
{
	int n,m,t;
	cin>>n>>m>>t;
	if(t==0)
	{
		cout<<"both "<<0<<endl;
		return 0; 
	}
	for(int i=0;i<t;i++)
	{
		int a,b;
		cin>>a>>b;
		hang[a]++;
		lie[b]++;
	}
	int hp=t/n;
	int lp=t/m;
	sumh[0]=hang[0]-hp;
	suml[0]=lie[0]-lp;
	
	for(int i=1;i<n;i++)
	{
		sumh[i]=(sumh[i-1]+(hang[i]-hp));
	}
	sort(sumh,sumh+n);
	for(int i=1;i<m;i++)
	{
		suml[i]=(suml[i-1]+(lie[i]-lp));
	}
	sort(suml,suml+m);
	ll ans=0;
	if(t%n==0&&t%m==0)
	{
		for(int i=0;i<n;i++)
		{
			ans+=1ll*abs(sumh[i]-sumh[n/2]);
		}
		for(int i=0;i<m;i++)
		{
			ans+=1ll*abs(suml[i]-suml[m/2]);
		}
		cout<<"both "<<ans<<endl;
	}
	else if(t%n==0)
	{
		for(int i=0;i<n;i++)
		{
			ans+=1ll*abs(sumh[i]-sumh[n/2]);
		}
		cout<<"row "<<ans<<endl;
	}
	else if(t%m==0)
	{
		for(int i=0;i<m;i++)
		{
			ans+=1ll*abs(suml[i]-suml[m/2]);
		}
		cout<<"column "<<ans<<endl;
	}
	else
	{
		cout<<"impossible"<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值