51nod1488 帕斯卡小三角形

题目

在这里插入图片描述
题目链接

解题思路

首先有一个关键性质:我们一定是从某个点开始一直往下走,然后一直往右下走。
( 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]+(xy+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;
}

猜你喜欢

转载自blog.csdn.net/qq_39586831/article/details/115338241