利普希茨

利普希茨

題目鏈接:jozj 5236jozj\ 5236

題目

在這裏插入圖片描述

輸入

輸入文件名爲lipschitz.inlipschitz.in
第一行一個整數nn
接下來一行nn個整數,描述序列AA
第三行一個數qq
接下來qq行,每行三個整數。其中第一個整數typetype表示操作的類型。type ⁣= ⁣0type\!=\!0對應修改操作, type ⁣= ⁣1type\!=\!1對應查詢操作。

輸出

輸出文件名爲lipschitz.outlipschitz.out
對於每個查詢,給出f(A[l..r])f(A[l..r])

樣例輸入1

6
90 50 78 0 96 20
6
0 1 35
1 1 4
0 1 67
0 4 11
0 3 96
1 3 5

樣例輸出1

78
85

樣例輸入2

50
544 944 200 704 400 150 8 964 666 596 850 608 452 103 988 760 370 723 350 862 856 0 724 544 668 891 575 448 16 613 952 745 990 459 740 960 752 194 335 575 525 12 618 80 618 224 240 600 562 283
10
1 6 6
1 1 3
0 11 78279
0 33 42738
0 45 67270
1 1 26
1 19 24
1 37 39
1 8 13
0 7 64428

樣例輸出2

0
744
77683
856
558
77683

數據範圍

對於30%30\%的數據,n,q ⁣<= ⁣500n,q\!<=\!500
對於60%60\%的數據,n,q ⁣<= ⁣5000n,q\!<=\!5000
對於100%100\%的數據,n,q ⁣<= ⁣100000,0 ⁣<= ⁣ai,val ⁣<= ⁣109n,q\!<=\!100000,0\!<=\!ai,val\!<=\!10^9

思路

這道題是線段樹。

我們先判斷怎麼處理查詢操作。
通過證明我們可以得出查詢的最優答案一定是選擇兩個相鄰的數。
具體證明看這位大佬的博客==>點這裏

那剩下的就簡單了,就線段樹咯。

代碼

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int n, a[100001], b[100001], tree[800001], q, x, y, z, ans;

void build(int now, int l, int r) {//建樹
	if (l == r) {
		tree[now] = b[l];
		return ;
	}
	
	int mid = (l + r) >> 1;
	build(now << 1, l, mid);
	build(now << 1 | 1, mid + 1, r);
	tree[now] = max(tree[now << 1], tree[now << 1 | 1]);
}

void getans(int now, int l, int r, int wl, int wr) {//求值
	if (l == wl && r == wr) {
		ans = max(ans, tree[now]);
		return ;
	}
	
	int mid = (l + r) >> 1;
	if (wr <= mid) getans(now << 1, l, mid, wl, wr);
		else if (wl > mid) getans(now << 1 | 1, mid + 1, r, wl, wr);
			else {
				getans(now << 1, l, mid, wl, mid);
				getans(now << 1 | 1, mid + 1, r, mid + 1, wr);
			}
}

void change(int now, int l, int r, int wh, int val) {//改值
	if (l == r) {
		tree[now] = val;
		return ;
	}
	
	int mid = (l + r) >> 1;
	if (wh <= mid) change(now << 1, l, mid, wh, val);
		else change(now << 1 | 1, mid + 1, r, wh, val);
	tree[now] = max(tree[now << 1], tree[now << 1 | 1]);
}

int main() {
//	freopen("lipschitz.in", "r", stdin);
//	freopen("lipschitz.out", "w", stdout);
	
	scanf("%d", &n);//讀入
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);//讀入
		b[i - 1] = abs(a[i] - a[i - 1]);//求相鄰數的絕對值
	}
	
	build(1, 1, n - 1);//建樹
	
	scanf("%d", &q);//讀入
	for (int Q = 1; Q <= q; Q++) {
		scanf("%d %d %d", &x, &y, &z);//讀入
		if (x) {//求值
			ans = 0;
			if (y != z) getans(1, 1, n - 1, y, z - 1);
			printf("%d\n", ans);//輸出
		}
		else {//改值
			a[y] = z;
			b[y - 1] = abs(a[y] - a[y - 1]);//修改會牽連到兩個
			b[y] = abs(a[y + 1] - a[y]);
			change(1, 1, n - 1, y - 1, b[y - 1]);
			change(1, 1, n - 1, y, b[y]);
		}
	}
	
//	fclose(stdin);
//	fclose(stdout);
	
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章