1. 程式人生 > >luogu P3932 浮遊大陸的68號島

luogu P3932 浮遊大陸的68號島

lib while inf read efi 簡單的 區間 fin 由於

有一天小妖精們又在做遊戲。這個遊戲是這樣的。

妖精倉庫的儲物點可以看做在一個數軸上。每一個儲物點會有一些東西,同時他們之間存在距離。

每次他們會選出一個小妖精,然後剩下的人找到區間[l,r]儲物點的所有東西,清點完畢之後問她,把這個區間內所有儲物點的東西運到另外一個倉庫的代價是多少?

比如儲物點i有x個東西,要運到儲物點jj,代價為 x*dist(i,j)

dist就是倉庫間的距離。

當然啦,由於小妖精們不會算很大的數字,因此您的答案需要對19260817取模

輸入輸出格式

輸入格式:

第一行兩個數表示n,m

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

第三行n個數,表示每個儲物點的東西個數

之後m行每行三個數x l r

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

輸出格式:

對於每個詢問輸出一個數表示答案

【分析】

關於今天考試找了個題練練手……

沒想到比考試還簡單 連個修改都沒有

和考試那個題的區別在於多了相鄰點之間的距離dist

推一下每個詢問的答案

就是 ∑(i=l~r)a[i] * abs(d[i]-d[x])

化簡一下就是 abs(∑(i=l~r)(a[i]*d[x]) - ∑(i=l~r)(a[i]*d[i]))

然後a[i]*d[i]可以預處理出來區間和 正負也顯然分成x左右就解決了

總之還是比較簡單的

(如果帶修改樹狀數組維護一下?)

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #define rep(i,a,n) for(int i = a;i <= n;i++)
 6 #define per(i,n,a) for(int i = n;i >= a;i--)
 7 #define inf 2147483647
 8 using namespace std;
 9 typedef long long ll;
10 ll read() {
11 ll as = 0,fu = 1; 12 char c = getchar(); 13 while(c < 0 || c > 9) { 14 if(c == -) fu = -1; 15 c = getchar(); 16 } 17 while(c >= 0 && c <= 9) { 18 as = as * 10 + c - 0; 19 c = getchar(); 20 } 21 return as * fu; 22 } 23 const int mod = 19260817; 24 const int N = 200006; 25 //head 26 ll n,m; 27 ll a[N],d[N]; 28 ll sa[N],mlt[N]; 29 ll calc(int l,int r,int x,bool op) { 30 if(l > r) return 0; 31 ll tmp1 = (sa[r] - sa[l-1]) % mod + mod; 32 tmp1 = tmp1 * d[x] % mod; 33 ll tmp2 = (mlt[r] - mlt[l-1]) % mod + mod; 34 if(op) swap(tmp1,tmp2); 35 return ((tmp1-tmp2)%mod+mod)%mod; 36 } 37 38 int main() { 39 n = read(); 40 m = read(); 41 rep(i,2,n) { 42 d[i] = (d[i-1] + read()) % mod; 43 } 44 rep(i,1,n) { 45 a[i] = read() % mod; 46 sa[i] = (sa[i-1] + a[i]) % mod; 47 mlt[i] = (mlt[i-1] + a[i] * d[i]) % mod; 48 } 49 rep(i,1,m) { 50 int x = read(),l = read(),r = read(); 51 ll ansl = calc(l,min(x-1,r),x,0); 52 ll ansr = calc(max(l,x+1),r,x,1); 53 printf("%lld\n",(ansl+ansr) % mod); 54 } 55 return 0; 56 }

OK啦

luogu P3932 浮遊大陸的68號島