P3932 浮游大陸的68號島

wyl123ly發表於2024-10-15

P3932 浮游大陸的68號島

題意

第二行 \(n - 1\) 個數,第 \(i\) 個數表示第 \(i\) 個儲物點與第 \(i + 1\) 個儲物點的距離

\(n\) 個儲物點,每個儲物點 \(i\)\(x\) 個東西,要運到儲物點 \(j\),代價為

\[x \times \mathrm{dist}( i , j ) \]

dist就是倉庫間的距離。

之後 \(m\) 行每行三個數x l r

表示查詢要把區間 \([l,r]\) 儲物點的物品全部運到儲物點x的花費

對於100%的資料 ,$ n , m \le 200000 ; a_i , b_i <= 2\cdot 10^9$

您的答案需要對19260817取模。

解法

首先把題意轉換成數學形式化語言:

對於一次查詢,我們的花費是:

\[\sum^{r}_{i = l} \left | pre_i - pre_x \right | \times a_i \]

其中 \(pre_i\) 表示儲物點 \(1\) 到儲物點 \(i\) 的距離。

發現有絕對值,那麼就需要我們對 \(x\) 的大小進行分類討論。

  1. \(x \le l\)

此時 \(pre_x \le pre_i\),所以直接去掉絕對值即可:

\[\sum^{r}_{i = l} \left ( pre_i - pre_x \right ) \times a_i\\ = \sum^{r}_{i = l} pre_i \times a_i - pre_x \times \sum^{r}_{i = l} a_i\\ \]

我們設 \(prea_i\)\(pre_i \times a_i\) 的字首和,\(aa_k\)\(\sum^{k}_{i = 1} a_i\)

則式子變為:

\[\left( prea_r - prea_{l - 1} \right) - pre_x \times \left( aa_r - aa_l - 1 \right) \]

可以 \(O(1)\) 計算。

  1. \(x \ge r\)

1的情況同理,可以得到計算式為:

\[pre_x \times \left( aa_r - aa_{l - 1} \right) - \left( prea_r - prea_{l - 1} \right) \]

  1. \(l < x < r\)

答案可以看成:

\[\sum^{x}_{i = l} \left( pre_x - pre_i \right) \times a_i + \sum^{r}_{i = x} \left( pre_i - pre_x \right) \times a_i \]

化簡後可以得到:

\[\left( prea_x - prea_{l - 1} \right) + pre_x \times \left( aa_x - aa_{l - 1} \right) + \left( prea_r - prea_{x - 1} \right) + pre_x \times \left( aa_r - aa_{x - 1} \right) \]

那麼我們只要預處理出 \(pre_i \times a_i\)\(a_i\)\(dis_i\),的字首和就可以了。

code:

#include<iostream>
#include<algorithm>
using namespace std;
const int MOD = 19260817;
const int MAXN = 2e5 + 1;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void write(int x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+'0');return;}

int n,m;
int d[MAXN];
int a[MAXN];
long long prea[MAXN],pre[MAXN];
long long aaa[MAXN];
int xx,ll,rr;
int ans = 0;
int solve(int x,int l,int r){
	ans = 0;
	if(x <= l){
		ans = ((ans + prea[r] - prea[l - 1]) % MOD + MOD) % MOD;
		ans = (((ans - pre[x] * aaa[r]) % MOD + MOD) % MOD + pre[x] * aaa[l - 1]) % MOD;
	}else if(x >= r){
		ans = ((ans + pre[x] * (aaa[r] - aaa[l - 1])) % MOD + MOD) % MOD;
		ans = ((ans - (prea[r] - prea[l - 1])) % MOD + MOD) % MOD;
	}else{
		ans = ((ans + pre[x] * aaa[x] - pre[x] * aaa[l - 1] % MOD) + MOD) % MOD;
		ans = ((ans - (prea[x] - prea[l - 1])) % MOD + MOD) % MOD;
		
		ans = ((ans + prea[r] - prea[x - 1]) % MOD + MOD) % MOD;
		ans = ((((ans - pre[x] * aaa[r]) % MOD + MOD) + pre[x] * aaa[x - 1]) % MOD + MOD) % MOD;
	}
	return ans;
}
int i;
signed main(){
	n = read();m = read();
	for(i = 1;i < n;i++) d[i] = read(),d[i] %= MOD;
	for(i = 1;i <= n;i++) a[i] = read(),a[i] %= MOD;
	for(i = 1;i <= n;i++) aaa[i] = (aaa[i - 1] + a[i]) % MOD;
	for(i = 1;i <= n;i++) pre[i] = (pre[i - 1] + d[i - 1]) % MOD;
	for(i = 1;i <= n;i++) prea[i] = (prea[i - 1] + (pre[i] * a[i])) % MOD;
	for(i = 1;i <= m;i++){
		xx = read(),ll = read(),rr = read();
		write(solve(xx,ll,rr));
		printf("\n");
	}
	return 0;
}

相關文章