[Luogu3932] 浮遊大陸的68號島
題目背景
大樣例下發鏈接: https://pan.baidu.com/s/1nuVpRS1 密碼: sfxg
浮遊大陸的68號島,位於浮遊大陸的邊境地帶。平時很少有人造訪。
島上被濃厚的森林覆蓋。
在這座邊境地區不起眼的浮遊島上,建立著神秘的”兵器“管理倉庫——妖精倉庫。
題目描述
妖精倉庫裏生活著黃金妖精們,她們過著快樂,卻隨時準備著迎接死亡的生活。
換用更高尚的說法,是隨時準備著為這個無藥可救的世界獻身。
然而孩子們的生活卻總是無憂無慮的,幼體的黃金妖精們過著天真爛漫的生活,自然也無暇考慮什麽拯救世界之類的重任。
有一天小妖精們又在做遊戲。這個遊戲是這樣的。
妖精倉庫的儲物點可以看做在一個數軸上。每一個儲物點會有一些東西,同時他們之間存在距離。
每次他們會選出一個小妖精,然後剩下的人找到區間[l,r][l,r][l,r]儲物點的所有東西,清點完畢之後問她,把這個區間內所有儲物點的東西運到另外一個倉庫的代價是多少?
比如儲物點iii有xxx個東西,要運到儲物點jjj,代價為
x×dist(i,j)x \times \mathrm{dist}( i , j )x×dist(i,j)
dist就是倉庫間的距離。
當然啦,由於小妖精們不會算很大的數字,因此您的答案需要對19260817取模。
輸入輸出格式
輸入格式:第一行兩個數表示n,mn,mn,m
第二行n−1n-1n−1個數,第iii個數表示第iii個儲物點與第i+1i+1i+1個儲物點的距離
第三行nnn個數,表示每個儲物點的東西個數
之後mmm行每行三個數x l r
表示查詢要把區間[l,r][l,r][l,r]儲物點的物品全部運到儲物點x的花費
輸出格式:對於每個詢問輸出一個數表示答案
輸入輸出樣例
輸入樣例#1: 復制5 5 2 3 4 5 1 2 3 4 5 1 1 5 3 1 5 2 3 3 3 3 3 1 5 5輸出樣例#1:
125 72 9 0 70
說明
對於30%的數據,n,m≤1000n , m \le 1000n,m≤1000
對於另外20%的數據,所有儲物點間的距離都為1
對於另外20%的數據,所有儲物點的物品數都為1
對於100%的數據 ,n,m≤200000;ai,bi<=2⋅109 n , m \le 200000 ; a_i , b_i <= 2\cdot 10^9n,m≤200000;ai?,bi?<=2⋅109
前綴和的應用。
比如我們要求$x$左邊的貢獻。
$\large ans=\sum|d[x]-d[i]|*a[i]$
$\large =\sum d[x]*a[i]-d[i]*a[i]$
$\large =d[x]*\sum a[i]-\sum d[i]*a[i]$
$x$右邊的同理。
所以我們可以計算$\large \sum a[i]$和$\large \sum d[i]*a[i]$就行了。
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cstdlib> using namespace std; #define reg register #define int long long inline int read() { int res = 0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } #define mod 19260817 #define N 200005 int n, m; int sigmaA[N], sigmaDa[N]; int d[N], a[N]; signed main() { n = read(), m = read(); for (reg int i = 2 ; i <= n ; i ++) { d[i] = read(); d[i] = (d[i] + d[i-1]) % mod; } for (reg int i = 1 ; i <= n ; i ++) { a[i] = read(); sigmaA[i] = (sigmaA[i-1] + a[i]) % mod; sigmaDa[i] = (sigmaDa[i-1] + d[i] * a[i] % mod) % mod; } while(m--) { int x = read(), l = read(), r = read(); int ans = 0; if (x < l) { ans = -d[x] * (sigmaA[r] - sigmaA[l-1]) % mod + (sigmaDa[r] - sigmaDa[l-1]); printf("%lld\n", (ans % mod + mod) % mod); continue; } if (x > r) { ans = d[x] * (sigmaA[r] - sigmaA[l-1]) % mod - (sigmaDa[r] - sigmaDa[l-1]); printf("%lld\n", (ans % mod + mod) % mod); continue; } ans = d[x] * (sigmaA[x] - sigmaA[l-1]) % mod - (sigmaDa[x] - sigmaDa[l-1]); ans = (ans + (-d[x] * (sigmaA[r] - sigmaA[x]) % mod + (sigmaDa[r] - sigmaDa[x])) % mod) % mod; printf("%lld\n", (ans % mod + mod) % mod); } return 0; }
[Luogu3932] 浮遊大陸的68號島