题目
解题思路
首先有一个关键性质:我们一定是从某个点开始一直往下走,然后一直往右下走。
从 ( 1 , i ) (1,i) (1,i)走到 ( x , y ) (x,y) (x,y)的代价是 s u m [ y ] − s u m [ i ] + ( x − y + i ) ∗ a [ i ] sum[y]-sum[i]+(x-y+i)*a[i] sum[y]−sum[i]+(x−y+i)∗a[i]。
由于查询的是整点,我们直接使用李超树维护下凸壳即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
#define lson rt * 2
#define rson rt * 2 + 1
typedef long long ll;
void read(int &x) {
x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
}
void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e5 + 100;
struct node {
int l, r, id;
}qu[N];
bool operator < (node a, node b) {
return a.r < b.r;
}
int n, m;
int sa[N], sum[N], ans[N];
int get(int i, int d) {
if (i == 0) return 1e9;
return -sum[i] + (i - d) * sa[i];
}
int tree[N * 4];
void insert(int id, int l, int r, int rt) {
if (tree[rt] == 0) return void(tree[rt] = id);
int m = (l + r) / 2;
if (get(tree[rt], m) > get(id, m)) swap(tree[rt], id);
if (l == r) return;
if (get(tree[rt], r) > get(id, r)) insert(id, m + 1, r, rson);
else insert(id, l, m, lson);
}
void insert(int rl, int rr, int id, int l, int r, int rt) {
if (rl == l && rr == r) return void(insert(id, l, r, rt));
int m = (l + r) / 2;
if (rr <= m) insert(rl, rr, id, l, m, lson);
else if (m < rl) insert(rl, rr, id, m + 1, r, rson);
else {
insert(rl, m, id, l, m, lson);
insert(m + 1, rr, id, m + 1, r, rson);
}
}
int query(int id, int l, int r, int rt) {
if (l == r) return get(tree[rt], id);
int m = (l + r) / 2;
if (id <= m) return min(get(tree[rt], id), query(id, l, m, lson));
else return min(get(tree[rt], id), query(id, m + 1, r, rson));
}
int main() {
//freopen("0.txt", "r", stdin);
read(n);
for (int i = 1; i <= n; i++) read(sa[i]), sum[i] = sum[i - 1] + sa[i];
read(m);
for (int i = 1; i <= m; i++) read(qu[i].l), read(qu[i].r), qu[i].id = i;
sort(qu + 1, qu + m + 1);
for (int i = 1, j = 1; i <= n && j <= m; i++) {
insert(0, i, i, 0, n, 1);
while (j <= m && qu[j].r == i) {
ans[qu[j].id] = sum[i] + query(qu[j].r - qu[j].l, 0, n, 1);
j++;
}
}
for (int i = 1; i <= m; i++) write(ans[i]), puts("");
return 0;
}