论将区间和转化为前缀和的重要性
这题一旦转化为前缀和就非常明了了
一段区间[l,r]的美妙程度就等于s[r]-s[l-1]
对于这种无法计算出所有方案而取前k大的题目,我们一般分类别然后利用类别内的单调性用堆维护
对于以i开头的区间,显然最美的长度在[l,r]之间的区间和
显然是max(s[i+l-1~i+r-1]),设这个最美的为k
次美的就是max(max(s[i+l-1~k-1]),max(s[k+1~i+r-1]),以此类推
不难想到用ST预处理区间前缀最大值
然后用大根堆维护开头为i,末端点位置在[p,q]上的最大值,
每次取出当前堆最大值,设在k取到最大值,就将这个区间裂位[p,k-1],[k+1,q]两个区间加入堆
一共进行k次,总的复杂度大约是O(klogn+nlogn)
讲的可能不是很清楚,具体见程序吧

bzoj2006_stbzoj2006_堆_02
  1 type node=record
  2        tl,tr,st,loc:longint;
  3        num:int64;
  4      end;
  5 
  6 var heap:array[0..1000010] of node;
  7     d:array[0..30] of longint;
  8     f:array[0..500010,0..30] of longint;
  9     s:array[0..500010] of longint;
 10     n,k,l,r,i,j,x,y,t,p:longint;
 11     ans:int64;
 12 
 13 function max(a,b:longint):longint;
 14   begin
 15     if s[a]>s[b] then exit(a) else exit(b);
 16   end;
 17 
 18 function min(a,b:longint):longint;
 19   begin
 20     if a>b then exit(b) else exit(a);
 21   end;
 22 
 23 function ask(x,y:longint):longint;
 24   var k:longint;
 25   begin
 26     k:=trunc(ln(y-x+1)/ln(2));
 27     exit(max(f[x,k],f[y-d[k]+1,k]));
 28   end;
 29 
 30 procedure insert(i,x,y:longint);
 31   begin
 32     heap[t].tl:=x;
 33     heap[t].tr:=y;
 34     heap[t].st:=i;
 35     heap[t].loc:=ask(x,y);
 36     heap[t].num:=s[heap[t].loc]-s[i-1];
 37   end;
 38 
 39 procedure swap(var a,b:node);
 40   var c:node;
 41   begin
 42     c:=a;
 43     a:=b;
 44     b:=c;
 45   end;
 46 
 47 procedure up(i:longint);
 48   var j:longint;
 49   begin
 50     j:=i shr 1;
 51     while j>0 do
 52     begin
 53       if heap[i].num>heap[j].num then
 54       begin
 55         swap(heap[i],heap[j]);
 56         i:=j;
 57         j:=i shr 1;
 58       end
 59       else break;
 60     end;
 61   end;
 62 
 63 procedure sift(i:longint);
 64   var j:longint;
 65   begin
 66     j:=i shl 1;
 67     while j<=t do
 68     begin
 69       if (j<t) and (heap[j].num<heap[j+1].num) then inc(j);
 70       if heap[i].num<heap[j].num then
 71       begin
 72         swap(heap[i],heap[j]);
 73         i:=j;
 74         j:=i shl 1;
 75       end
 76       else break;
 77     end;
 78   end;
 79 
 80 begin
 81   readln(n,k,l,r);
 82   for i:=1 to n do
 83   begin
 84     readln(x);
 85     s[i]:=s[i-1]+x;
 86     f[i,0]:=i;
 87   end;
 88   t:=trunc(ln(n)/ln(2));
 89   d[0]:=1;
 90   for i:=1 to t do
 91     d[i]:=d[i-1]*2;
 92   for j:=1 to t do
 93     for i:=1 to n do
 94       if i+d[j]-1<=n then
 95         f[i,j]:=max(f[i,j-1],f[i+d[j-1],j-1])
 96       else break;
 97   t:=0;
 98   for i:=1 to n-l+1 do
 99   begin
100     inc(t);
101     insert(i,i+l-1,min(i+r-1,n));
102     up(i);
103   end;
104   for i:=1 to k do
105   begin
106     p:=heap[1].loc;
107     x:=heap[1].tl;
108     y:=heap[1].tr;
109     j:=heap[1].st;
110     ans:=ans+int64(heap[1].num);
111     swap(heap[1],heap[t]);
112     dec(t);
113     sift(1);
114     if p>x then
115     begin
116       inc(t);
117       insert(j,x,p-1);
118       up(t);
119     end;
120     if p<y then
121     begin
122       inc(t);
123       insert(j,p+1,y);
124       up(t);
125     end;
126   end;
127   writeln(ans);
128 end.
129 
130  
View Code