edu round 161 C Closest Cities

题意

有t组数据,每组数据包括一个n,表示接下来数组a中元素的个数。有一个单调递增的数组a,a[i]表示每个城市在一个数轴上的坐标,对于每个城市,都有唯一的一个最近城市(左右城市的其中之一),前往最近城市所需要的钱为1,非最近城市所需要的钱为两坐标之差,接下来m个询问,每个询问求出从l城市走到r城市所需要的最少的钱。

输入

1
5
0 8 12 15 20
5
1 4
1 5
3 4
3 2
5 1


输出

3
8
1
4
14

思路

按照走的方向分为从前面往后面和从后面往前面两种走法,分别用前缀和,后缀和来写,b,c中分别存储从前面往后面走和从后面往前面走的累计钱数,l,r表示出发城市和目的城市,若出发城市坐标小于目的城市坐标,则b[r]-b[l],反过来同理。

#include 
using namespace std;
typedef long long ll;

int main() {
	int t;
	cin >> t;
	while (t--) {
		int n;//b[i]表示从第一个城市到第i个城市累计所需要的钱
		cin >> n;
		vectora(n + 1);
		vectorb(n + 1, 0); //累计价格差分数组,从前到后
		vectorc(n + 1, 0); //从后到前
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		for (int i = 1; i < n; i++) { //从前到后
			b[i] += b[i - 1];
			if ((a[i + 1] - a[i] < a[i] - a[i - 1]) || i == 1) { //下一个城市是最近城市
				b[i + 1] += 1;
			} else {
				b[i + 1] += (a[i + 1] - a[i]);
			}
		}
		b[n] += b[n - 1];//到最后一个城市的钱还需加上前一个的,因为在循环里没加上
		c[n - 1] = 1;
		for (int i = n - 1; i > 1; i--) { //从后往前
			c[i] += c[i + 1];
			if (a[i] - a[i - 1] < a[i + 1] - a[i])
				c[i - 1] += 1;
			else
				c[i - 1] += ( a[i] - a[i - 1]);

		}
		c[1] += c[2];//同上,类似于b数组最后一个数的处理办法
		int m;
		cin >> m;
		while (m--) {
			int l, r;
			scanf("%d%d", &l, &r);
			ll ans = 0;
			if (l < r) { //从前往后走
				ans = b[r] - b[l];
				cout << ans << endl;
			} else {//从后往前走
				ans = c[r] - c[l];
				cout << ans << endl;
			}
		}
	}
}

你可能感兴趣的:(cf补题,算法,c++)