晚上发现NOI不给用优先级队列,就自己写个堆,还行,速度
#include <cstdio> const int N = (500000 + 1234) * 2; struct heap_node { int value, l, r, minv, loc; heap_node(int v1,int l1,int r1,int minv1, int loc1) { value = v1; l = l1; r = r1; minv = minv1; loc = loc1; } heap_node() {} }; void swap(int& a, int& b) { int temp = a; a = b; b = temp; } int max(int a, int b) { if(a > b) return a; return b; } //int mark; class Heap { public: int size; int heap[N]; int l[N], r[N], minv[N], loc[N]; void init() { size=0; heap[0]=1<<30; } void adjust(int i) { int j; if (heap[i]>heap[i>>1]) { for ( ; heap[i]>heap[i>>1]; i=j) { j=i>>1; //if(j == 0) break; swap(heap[i], heap[j]); swap(l[i], l[j]); swap(r[i], r[j]); swap(minv[i], minv[j]); swap(loc[i], loc[j]); } //mark = i; } else { for (j=i; ; i=j) { if ((i<<1)<=size && heap[j]<heap[i<<1] ) j=i<<1; if ( (i<<1)+1<=size && heap[j]<heap[(i<<1)+1] ) j=(i<<1)+1; if (j==i) break; swap(heap[i], heap[j]); swap(l[i], l[j]); swap(r[i], r[j]); swap(minv[i], minv[j]); swap(loc[i], loc[j]); } //mark = i; } } void push(heap_node c) { ++size; heap[size]=c.value; l[size] = c.l; r[size] = c.r; minv[size] = c.minv; loc[size] = c.loc; adjust(size); } heap_node pop() { swap(heap[1], heap[size]); swap(l[1], l[size]); swap(r[1], r[size]); swap(minv[1], minv[size]); swap(loc[1], loc[size]); if (--size) adjust(1); heap_node t(heap[size+1], l[size+1], r[size+1], minv[size+1], loc[size+1]); return t; } } hp; int st[19][500001];//RMQ是用的数组 int s[500001], log[500001]; int Query_RMQ(int a, int b) { int loc = log[b-a+1];//2的多少次方 if (s[st[loc][a]] < s[st[loc][b-(1<<loc)+1]]) return st[loc][a]; else return st[loc][b-(1<<loc)+1]; } int main() { // freopen("piano5.in","r",stdin); int n, k, L, R, i, j, x, minv, t1, t2; long long ans; heap_node tmp; scanf("%d%d%d%d", &n, &k, &L, &R); for (s[0] = 0, i = 1; i <= n; i ++) //前缀和 scanf("%d", &x), s[i] = s[i-1] + x; for (log[1] = 0, i = 2; i <= n; i ++) log[i] = log[i-1] + ((i & -i) == i); for (i = 1; i <= n; i ++) st[0][i] = i - 1; for (i = 1; 1 << i <= n; i ++) for (j = 1; j + (1 << i) - 1 <= n; j ++) if (s[st[i-1][j]] < s[st[i-1][j+(1<<i-1)]]) st[i][j] = st[i-1][j]; else st[i][j] = st[i-1][j+(1<<i-1)]; hp.init(); for (i = L; i <= n; i ++) { t1 = max(1, i - R + 1), t2 = i - L + 1;//找到左端点所在的区间 minv = Query_RMQ(t1, t2); heap_node t(s[i] - s[minv], t1, t2, minv + 1, i); //和,左端点所在的区间两个端点,最小值所在的序号,右端点 hp.push(t); //if(i==351288) printf("mark=%d\n",mark); } for (ans = 0, i = 1; i <= k; i ++) { tmp = hp.pop(); ans += tmp.value; if (tmp.l < tmp.minv) { t1 = tmp.l, t2 = tmp.minv - 1; minv = Query_RMQ(t1, t2); heap_node t(s[tmp.loc] - s[minv], t1, t2, minv + 1, tmp.loc); hp.push(t); } if (tmp.minv < tmp.r) { t1 = tmp.minv + 1, t2 = tmp.r; minv = Query_RMQ(t1, t2); heap_node t(s[tmp.loc] - s[minv], t1, t2, minv + 1, tmp.loc); hp.push(t); } } printf("%I64d\n", ans); return 0; }