储物点的距离

储物点的距离

http://www.nowcoder.com/questionTerminal/957aa3864e2e4663b58a9a7ca6cd513c

题意:
一个数轴,每一个储物点会有一些东西,同时它们之间存在距离。
每次给个区间[l,r],查询把这个区间内所有储物点的东西运到另外一个储物点的代价是多少?
比如储物点i有x个东西,要运到储物点j,代价为x * dist( i , j )
dist就是储物点间的距离。
题解:
首先将储物点之间的距离转换成在数轴上的点,a[i]:储物点在数轴上的位置,b[i]:储物点内物品数量;
将区间[l,r]内的储物点转移到x储物点,首先我们考虑l<=x<=r的情况;
可以化简为:

查询区间值的和——前缀和来处理这个式子:
s1[i]=s1[i-1]+a[i]*b[i],s2[i]=s2[i]+b[i];
预处理之后,那么对于询问我们可以在O(1)时间内得出答案。
对于x<l和x>r的情况与上式相似,很容易得到。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=1e9+7;
void io() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); }
ll a[maxn],b[maxn];
int n,m;
ll s1[maxn],s2[maxn];
int main() {
	scanf("%d%d",&n,&m);
	ll s=1,x=0,l,r,y;	
	for(int i=1;i<=n-1;i++){
		scanf("%lld",&x);
		a[i]=s; s+=x;
	}
	a[n]=s;
	for(int i=1;i<=n;i++){
		scanf("%lld",b+i);
	}
	for(int i=1;i<=n;i++){
		s2[i]=(s2[i-1]+b[i])%mod;
	}
	for(int i=1;i<=n;i++){
		s1[i]=(s1[i-1]+a[i]%mod*b[i])%mod;
	}
	ll ans=0;
	while(m--){
		scanf("%lld%lld%lld",&y,&l,&r);
		x=a[y]; //x储物点在数轴上的位置 
		ans=0;
		if(l<=y&&y<=r){
			ans=((x%mod*(s2[y]-s2[l-1])%mod-(s1[y]-s1[l-1]))%mod);
			ans=(ans+(((s1[r]-s1[y])-x%mod*(s2[r]-s2[y]))%mod))%mod;
		} else if(y<l){
			ans=((s1[r]-s1[l-1])-x%mod*(s2[r]-s2[l-1]))%mod;
		} else {
			ans=((x%mod*(s2[r]-s2[l-1])%mod-(s1[r]-s1[l-1])))%mod;
		}
		//处理答案为负数的情况 
		while(ans<0) ans=(ans+mod)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}




全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 11:30
点赞 评论 收藏
分享
一tiao酸菜鱼:秋招还没正式开始呢,就准备有结果了。。。。?
点赞 评论 收藏
分享
05-26 10:24
门头沟学院 Java
qq乃乃好喝到咩噗茶:其实是对的,线上面试容易被人当野怪刷了
找工作时遇到的神仙HR
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务