acwing中位数之七夕祭

105. 七夕祭 - AcWing题库

本题首先我们可以知道当我们移动摊位来使得每一行的感兴趣的点数相同时并未改变每一列上的点的数量,同理将每一列上的点左右移动时并未改变行上点的总数量。由此我们可以分开计算,先算行上点的移动次数再算列上摊位的移动次数。经过感兴趣的摊位的总数量对行数与列数进行取余,判断是否为0,来决定感兴趣的点感兴趣的点数在行或列上能否均分。有个结论,以列为例,我们将一列看成一堆书本,书本的数量为这一列感兴趣的点的总数量,最少次数交换书本数来达到均分效果的分法,一定有两个书本堆没进行过交换。因为如果任意两堆书都要进行交换,肯定不是最优解,理想情况多的书的书堆往少的书的书堆传递书,最后达到均分的目的。(就是说环形书堆的最优分法肯定是链形书堆)(详细证明在这位大佬这里AcWing 105. 七夕祭-证明一定存在一个最优解是可以拆成链的 - AcWing

接下来我们知道了最优解一定是链形了后,我们将那两个没进行过书交换的书堆一刀切开,形成链子。接下来手写证明。一下证明我们均以列为例,我们将一列看成一堆书本,书本的数量为这一列感兴趣的点的总数量。(行同样如此)

我们从数值角度来看就是使得s【i】-s【k】的值最小,问题转化为s[k]代表了k的位置,s[i]代表了i商店的位置,总共m个商店,从中找到某个k商店,使得从他出发到各个商店的距离之和最小。根据中位数的知识,我们知道这个k 商店的位置一定位于所有商店的中位数的位置,由此我们只需要在一开始把前缀和数组排序,找到商店k的位置即可。本题结束。


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.AnnotatedWildcardType;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Spliterator.OfPrimitive;
import javax.management.relation.InvalidRelationTypeException;
import javax.print.attribute.standard.JobMessageFromOperator;
public class Main {
  public static void main(String[] args) throws IOException  {
Scanner sc=new Scanner(System.in);
aa=sc.nextInt();
bb=sc.nextInt();
cc=sc.nextLong();
xx=new long[aa+1];
yy=new long[bb+1];
int a,b,c;
for(a=0;a<cc;a++) {
	b=sc.nextInt();
	c=sc.nextInt();
	xx[b]++;
	yy[c]++;
	
}
if(cc%aa==0&&cc%bb==0) {
	System.out.println("both "+(getanswer(xx,aa)+getanswer(yy, bb)));
	//System.out.println("AAA");
}
else if(cc%aa==0&&cc%bb!=0) {
	System.out.println("row "+getanswer(xx, aa));
}
else if(cc%aa!=0&&cc%bb==0) {
	System.out.println("column "+getanswer(yy, bb));
}
else {
	System.out.println("impossible");
}
  }
  public static int aa;
  public static int bb;
  public static long cc;
  public static long jishu=0;
  public static long[] xx;
  public static long[] qianzhuihe; 
  public static long[] yy; 
  public static long getanswer(long[] a,int a1) {
	  //System.out.println(Arrays.toString(a));
		  int b;		 
		  int c=a.length;
		  long e=0;
		  qianzhuihe=new long[c];
		  for(b=1;b<c;b++) {
			  qianzhuihe[b]=qianzhuihe[b-1]+a[b]-cc/a1;
		  }
		  Arrays.sort(qianzhuihe,1,c);
		  for(b=1;b<c;b++) {
			  e=e+Math.abs(qianzhuihe[b]-qianzhuihe[(a1+1)/2]);
			 
		  }
		  return e;
  }
 }

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值