论将区间和转化为前缀和的重要性
这题一旦转化为前缀和就非常明了了
一段区间[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)
讲的可能不是很清楚,具体见程序吧
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