51nod1488パスカルの小さな三角形

トピック

ここに画像の説明を挿入
トピックリンク

問題解決のアイデア

まず、重要な特性があります。特定のポイントから開始して最後まで下がってから、右下まで下がる必要があります。(1、i)から(1、I)
1 i)走到 ( x , y ) (x,y) x y 的代价是和[y] −合計[i] +(x − y + i)∗ a [i]合計[y]-合計[i] +(x-y + i)* a [i]s u m [ y ]s u m [ i ]+xそして+i a [ i ]
クエリが要点なので、LiChaoshuを直接使用して下凸包を維持できます。

コード

#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