2018.10.02【校內模擬】聚會(字首和)
【描述】
在成都的一條街道上, 一共有 N 戶人家,每個家庭有 Xi 個人,他們和諧的生活在 一起,作為全國和諧街道,他們經常會小範圍組織活動,每次活動會選擇一戶作為聚點, 並要求某些家庭參加,為了方便通知,村長每次邀請位置連續的家庭。因為每戶人數不 同,每個家庭之間有一定距離,村長希望你計算出每次邀請的家庭的移動代價。 第 i 個家 庭移動到家庭 j 的代價是: Xi*dis(i,j) dis(i,j)表示 i 到 j 的距離,村長一共安排了 m 次聚會,每次邀請[Li, Ri]的家庭參加
【輸入】
第一行兩個數表示 n,m 第二行 n-1 個數,第 i 個數表示第 i 個家庭與第 i+1 個家庭的距離 Di 第三行 n 個數,表示每個家庭的人數 Xi 之後 m 行每行三個數 x l r, 表示查詢要把區間 [l,r]的家庭移動到 x 點的代價和
【輸出】
對於每個詢問輸出一個數表示答案,對 19260817 取模
【輸入樣例】
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
【輸出樣例】
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
【子任務】
對於 30%的資料, n,m≤1000 對於另外 20%的資料,所有家庭間的距離都為 1 對於另外 20%的資料,所有家庭人數都為 1 對於 100%的資料 , n,m≤200000;Xi, Di <=2*10^9
解析:
一堆同學減法不取模而爆零。我亂寫的程式碼還AC了。。。
其實程式碼裡面就已經有詳細註釋了(不過是英文),為什麼是英文呢,(因為考試的時候懶得切換輸入法)
思路:
顯然我們能夠做到回答每一個詢問。
我們用陣列表示從1到的距離,這樣就可以查詢任意兩個家庭之間的距離。 我們用陣列表示從1到所有家庭的人數和,這樣就可以查詢每一段區間的家庭人數總數。
接下來就是本題實現回答詢問的關鍵。 我們用陣列表示前到的所有家庭全部聚集到第個家庭的代價。 我們用陣列表示後到的所有家庭全部聚集到第個家庭的代價。
我們現在考慮當都在的前面的時候,移動到的所有家庭到的代價,記為。 都在後面的時候做相似考慮,記為。 而當在中間的時候,我們將詢問拆成和,採用上面兩種方式考慮。
我僅對做詳細說明,其餘請讀者自行思考,或者看程式碼裡面的註釋
首先,我們把前的所有家庭全部移動到,這個代價是。 然後我們把之前的人先暫時送回,這個代價是。 然後現在之前的人全部在位置,我們將他們全部送回自己的家的代價,就是將他們全部從家中召喚至家中代價的相反。這裡代價就是。 好了,現在到的所有人都在家中了。 我們再將他們從家中送去家,代價就是。
所以總的代價的式子真的很長,大家看一看程式碼吧。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
ll getint(){
re ll num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline
void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs ll mod=19260817;
cs int N=200005;
ll dist[N];//the distance from 1 to i
ll siz[N];//the total num fo people
ll pre[N];//move all 1-(i-1) to i
ll suf[N];//move all (i+1)-n to i
int n;
int m;
inline
ll querypre(int l,int r,int x){//l,r are all at previous poses
ll res=((pre[r]-pre[l]-siz[l-1]*(dist[r]-dist[l])%mod)+mod)%mod;//first move all to r
res+=(siz[r]-siz[l-1]+mod)%mod*((dist[x]-dist[r]+mod)%mod)%mod;//then move all to x
res%=mod;
res=(res+mod)%mod;
return res;
}
inline
ll querysuf(int l,int r,int x){//l,r,are all at suffix poses
ll res=(suf[l]-suf[r]-(siz[n]-siz[r]+mod)%mod*((dist[r]-dist[l])+mod)%mod+mod)%mod; //first move all to l
res+=(siz[r]-siz[l-1]+mod)%mod*((dist[l]-dist[x]+mod)%mod)%mod; //then move all to x
res%=mod;
res=(res+mod)%mod;
return res;
}
signed main(){
n=getint();
m=getint();
for(int re i=2;i<=n;++i)dist[i]=(dist[i-1]+getint())%mod;
for(int re i=1;i<=n;++i)siz[i]=(siz[i-1]+getint())%mod;
for(int re i=2;i<=n;++i){
pre[i]=(pre[i-1]+(dist[i]-dist[i-1])*siz[i-1]%mod)%mod;
}
for(int re i=n-1;i;--i){
suf[i]=(suf[i+1]+(siz[n]-siz[i])*(dist[i+1]-dist[i])%mod)%mod;
}
while(m--){
int x=getint(),l=getint(),r=getint();
if(l<x&&x<r){
outint((querypre(l,x-1,x)+querysuf(x+1,r,x))%mod);pc('\n');
continue;
}
if(x<=l){
if(l==x)++l;
outint(querysuf(l,r,x)),pc('\n');
continue;
}
if(x>=r){
if(x==r)--r;
outint(querypre(l,r,x));pc('\n');
continue;
}
}
return 0;
}