浏览器标题切换
浏览器标题切换end
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

AT2442 フェーン現象 (Foehn Phenomena)

题目地址

原题地址

题解

其实就是一个区间加,单点查询的问题
当然可以线段树/树状数组做,但是这两个做法要分类讨论所以代码会比较多
我们考虑一种更简便的做法
差分!
因为温度只和海拔差有关,这相当于题目赤裸裸的告诉我们要差分
那么我们考虑每次修改海拔对答案的影响
对于中间那一段,显然对答案的贡献是不会变的
会变的只有\(l,r+1\)这两个地方,分类讨论高低太麻烦了,我们可以先在答案中减去原来的数对答案的影响,再给答案加上修改后的数对答案的影响
代码语言即为

sum -= p(d[l]); d[l] += x; sum += p(d[l]);
//p为算影响的函数,d为差分数组,sum为答案

于是我们得到了一个预处理\(O(n)\),单次询问\(O(1)\)的算法
需要注意的一个点是,要特判\(r=n\)的情况,在这种情况下,我们只需要更改左端点即可
以及将差分数组和前缀和开longlong

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define N 200010
int n, m, s, t;
ll a[N], d[N];
ll sum = 0;

ll p(ll x) { return x * (x > 0 ? s : t); }

int main() {
	scanf("%d%d%d%d", &n, &m, &s, &t);
	ll L; scanf("%lld", &L);
	for(int i = 1; i <= n; i ++) {
		scanf("%lld", &a[i]);
		d[i] = a[i] - L; L = a[i];
		sum += p(d[i]);
	}
	for(int i = 1; i <= m; i ++) {
		int l, r; ll x;
		scanf("%d%d%lld", &l, &r, &x);
		sum -= p(d[l]); d[l] += x; sum += p(d[l]);
		if(r == n) {printf("%lld\n", -sum); continue;}
		sum -= p(d[r + 1]); d[r + 1] -= x; sum += p(d[r + 1]);
		printf("%lld\n", -sum);
	}
	return 0;
}
posted @ 2018-12-19 22:54  henry_y  阅读(216)  评论(0编辑  收藏  举报