【CF675C】Money Transfers(离散化,贪心)

http://www.cnblogs.com/chengsheng/p/5535316.html

题目大意:给你n个银行中的存款(负值表示借贷),是成环的,1跟n相接,这n个数的和为0。可以从i向i的相邻两侧转移存款,问你最少转移多少次,可以让所有银行的存款都为0。

解题思路:n个数的和为0,假设是由k个和为0的区间组成的。假设这些区间的长度为li,那么长度为li的区间需要li-1次转移。那么总共需要l1-1+l2-1+l3-1...+lk-1次转移,因为l1+l2+l3...lk=n,所以总共需要n-k次转移,这个k就是区间和为0的区间个数。我们通过求前缀和sum来统计区间和为0的个数。当sum[i] = sum[j]时,我们知道a[i+1]+...a[j]为0,这个区间和为0。所以我们记录sum=X出现的次数,n-time[X]来更新答案。

此题是均分纸牌(NOIP2002)强化(弱化?)版,此题1与n间可互换

C++自带离散化

排序里面MID没用INT64交了十多次终生遗憾

 

 1 var c,d:array[0..200000]of longint;
 2     a,s:array[0..200000]of  int64;
 3     n,i,ans:longint;
 4     t:int64;
 5 
 6 function min(x,y:longint):longint;
 7 begin
 8  if x<y then exit(x);
 9  exit(y);
10 end;
11 
12 procedure qsort(l,r:longint);
13 var i,j:longint;
14     mid:int64;
15 begin
16  i:=l; j:=r; mid:=s[(l+r) div 2];
17  repeat
18   while mid>s[i] do inc(i);
19   while mid<s[j] do dec(j);
20   if i<=j then
21   begin
22    t:=s[i]; s[i]:=s[j]; s[j]:=t;
23    inc(i); dec(j);
24   end;
25  until i>j;
26  if l<j then qsort(l,j);
27  if i<r then qsort(i,r);
28 end;
29 
30 begin
31  read(n);
32 // fillchar(s,sizeof(s),0);
33 // fillchar(c,sizeof(c),0);
34 // fillchar(d,sizeof(d),0);
35 //
36  for i:=1 to n do read(a[i]);
37  ans:=n-1;
38  for i:=1 to n do s[i]:=s[i-1]+a[i];
39 
40  qsort(1,n);
41  for i:=1 to n do
42   if (i=1)or(s[i]>s[i-1]) then c[i]:=c[i-1]+1
43    else c[i]:=c[i-1];
44 
45  for i:=1 to n do inc(d[c[i]]);
46  for i:=1 to n do ans:=min(ans,n-d[i]);
47  writeln(ans);
48 
49 end.
View Code

 

posted on 2016-05-30 20:57  myx12345  阅读(569)  评论(0编辑  收藏  举报

导航