【描述】
在成都的一条街道上, 一共有 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;
}