[luogu3932] 浮游大陆的68号岛

有一天小妖精们又在做游戏。这个游戏是这样的。

妖精仓库的储物点可以看做在一个数轴上。每一个储物点会有一些东西,同时他们之间存在距离。

每次他们会选出一个小妖精,然后剩下的人找到区间[l,r][l,r]储物点的所有东西,清点完毕之后问她,把这个区间内所有储物点的东西运到另外一个仓库的代价是多少?

比如储物点ii有xx个东西,要运到储物点jj,代价为

x \times \mathrm{dist}( i , j )x×dist(i,j)
dist就是仓库间的距离。

当然啦,由于小妖精们不会算很大的数字,因此您的答案需要对19260817取模。

输入输出格式

输入格式:
第一行两个数表示n,mn,m
第二行n-1n−1个数,第ii个数表示第ii个储物点与第i+1i+1个储物点的距离

第三行nn个数,表示每个储物点的东西个数

之后mm行每行三个数x 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

//真恶心,各种取mod

注意 (a - b) % mod ==> (a - b + mod) % mod

f[i] = xi | d[x] - d[i] | = | xi * d[x] - xi * d[i] |

∑f[i] = ∑ xi * d[x] - d[x] * ∑ xi ; (d[i]为 1 到 i 的距离和)
所以只要统计xi * di 的前缀和,和xi 的前缀和即可

无mod的爆0代码,便于理解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 200000 + 100;
int n,m;
int d[maxn],val[maxn],sx[maxn],xl[maxn];

int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int main() {
    n = read(), m = read();
    for(int i = 2; i <= n; i++) {
        d[i] = read();
        d[i] = d[i - 1] + d[i];
    }
    for(int i = 1; i <= n; i++) {
        val[i] = read();
        sx[i] = sx[i - 1] + val[i];
        xl[i] = xl[i - 1] + val[i] * d[i];	
    }
    while(m--) {
        int x = read(), l = read(), r = read(), sum = 0;
        if(x <= l) {
            sum = ( xl[r] - xl[l- 1] ) - d[x] * ( sx[r] - sx[l - 1] );
        }
        else if(x >= r) {
            sum = d[x] * ( sx[r] - sx[l - 1] ) - ( xl[r] - xl[l- 1] );
        }
        else {
            sum = d[x] * ( sx[x - 1] - sx[l - 1] ) - ( xl[x - 1] - xl[l- 1] );
            sum += ( xl[r] - xl[x] ) - d[x] * ( sx[r] - sx[x] );
        }
        cout<<sum<<endl;
    }
}

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 200000 + 100;
const int mod = 19260817;
long long n,m;
long long d[maxn],val[maxn],sx[maxn],xl[maxn];

long long read() {
    long long x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int main() {
	n = read(), m = read();
	for(int i = 2; i <= n; i++) {
		d[i] = read();
		d[i] = d[i - 1] + d[i];
		d[i] %= mod;
	}
	for(int i = 1; i <= n; i++) {
		val[i] = read();
		sx[i] = sx[i - 1] + val[i];
		sx[i] %= mod;
		xl[i] = xl[i - 1] + val[i] * d[i];	
		xl[i] %= mod;
	}
	while(m--) {
		long long x = read(), l = read(), r = read(), sum = 0;
		if(x <= l) {
			sum = ( ( xl[r] - xl[l- 1] + mod ) % mod - 
				d[x] * ( sx[r] - sx[l - 1] + mod ) % mod + mod ) % mod;
		}
		else if(x >= r) {
			sum = ( d[x] * ( sx[r] - sx[l - 1] + mod ) % mod -
				 ( xl[r] - xl[l- 1] + mod ) % mod  + mod ) % mod;
		}
		else {
			sum = ( d[x] * ( sx[x - 1] - sx[l - 1] + mod ) % mod -
				 ( xl[x - 1] - xl[l- 1] + mod ) % mod  + mod ) % mod;
			sum += ( ( xl[r] - xl[x] + mod ) % mod  -
				 d[x] * ( sx[r] - sx[x] + mod ) % mod + mod ) % mod;
			sum %= mod;
		}
		cout<<sum<<endl;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值