#P3408. 第3题-符文轮回咒
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 51
            Accepted: 15
            Difficulty: 4
            
          
          
          
                       所属公司 : 
                              阿里
                                
            
                        
              时间 :2025年8月17日-阿里云
                              
                      
          
 
- 
                        算法标签>思维          
 
第3题-符文轮回咒
思路
- 
轮回只会影响两端时的 A1 或 An:
- 区间不含两端(1<l 且 r<n):A1,An 不变,S 不变,候选为 A1−An。
 - 前缀(l=1):可把任意 Ak(1≤k≤r)旋到首位,因此可达最大 Amax−An。
 - 后缀(r=n):可把任意 Ak(l≤k≤n)旋到末位,因此可达 A1−Amin。
 - 整段(l=1,r=n):整体循环后 S(A′)=Ai−Ai−1(把相邻对视为环,A0=An),因此可达 max2≤i≤n(Ai−Ai−1) 以及 A1−An(当环相邻对取 (A_1,An))。
 
 - 
综上答案为下式四者最大:
- A1−An
 - A1−min(A)
 - max(A)−An
 - max2≤i≤n(Ai−Ai−1)
 
 - 
特判 n=1:答案为 0。
 - 
时间复杂度:O(n)(每组数据一次线性扫描)。
 
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int T;
	if (!(cin >> T)) return 0;
	while (T--) {
		int n;
		cin >> n;
		vector<long long> a(n);
		for (int i = 0; i < n; ++i) cin >> a[i];
		// 特判 n=1
		if (n == 1) {
			cout << 0 << "\n";
			continue;
		}
		long long mn = a[0], mx = a[0];
		for (int i = 1; i < n; ++i) {
			mn = min(mn, a[i]);
			mx = max(mx, a[i]);
		}
		// 候选1:原始 S(A) = A1 - An
		long long ans = a[0] - a[n-1];
		// 候选2:后缀旋转 -> A1 - min(A)
		ans = max(ans, a[0] - mn);
		// 候选3:前缀旋转 -> max(A) - An
		ans = max(ans, mx - a[n-1]);
		// 候选4:整段旋转 -> max(A_i - A_{i-1}),i=2..n
		for (int i = 1; i < n; ++i) {
			ans = max(ans, a[i] - a[i-1]);
		}
		cout << ans << "\n";
	}
	return 0;
}
Python
import sys
data = list(map(int, sys.stdin.read().strip().split()))
it = iter(data)
T = next(it, 0)
out_lines = []
for _ in range(T):
    n = next(it)
    a = [next(it) for _ in range(n)]
    # 特判 n=1
    if n == 1:
        out_lines.append("0")
        continue
    mn = min(a)
    mx = max(a)
    # 候选1:A1 - An
    ans = a[0] - a[-1]
    # 候选2:A1 - min(A)
    ans = max(ans, a[0] - mn)
    # 候选3:max(A) - An
    ans = max(ans, mx - a[-1])
    # 候选4:max(A_i - A_{i-1})
    for i in range(1, n):
        ans = max(ans, a[i] - a[i-1])
    out_lines.append(str(ans))
sys.stdout.write("\n".join(out_lines))
Java
import java.io.*;
import java.util.*;
public class Main {
	// 简单快读
	static class FastScanner {
		private final InputStream in;
		private final byte[] buffer = new byte[1 << 16];
		private int ptr = 0, len = 0;
		FastScanner(InputStream is) { in = is; }
		private int read() throws IOException {
			if (ptr >= len) {
				len = in.read(buffer);
				ptr = 0;
				if (len <= 0) return -1;
			}
			return buffer[ptr++];
		}
		long nextLong() throws IOException {
			int c; do { c = read(); } while (c <= ' ' && c != -1);
			long sgn = 1;
			if (c == '-') { sgn = -1; c = read(); }
			long x = 0;
			while (c > ' ') { x = x * 10 + (c - '0'); c = read(); }
			return x * sgn;
		}
		int nextInt() throws IOException { return (int) nextLong(); }
	}
	public static void main(String[] args) throws Exception {
		FastScanner fs = new FastScanner(System.in);
		StringBuilder sb = new StringBuilder();
		int T = fs.nextInt();
		while (T-- > 0) {
			int n = fs.nextInt();
			long[] a = new long[n];
			for (int i = 0; i < n; i++) a[i] = fs.nextLong();
			// 特判 n=1
			if (n == 1) {
				sb.append(0).append('\n');
				continue;
			}
			long mn = a[0], mx = a[0];
			for (int i = 1; i < n; i++) {
				if (a[i] < mn) mn = a[i];
				if (a[i] > mx) mx = a[i];
			}
			// 候选1:A1 - An
			long ans = a[0] - a[n - 1];
			// 候选2:A1 - min(A)
			ans = Math.max(ans, a[0] - mn);
			// 候选3:max(A) - An
			ans = Math.max(ans, mx - a[n - 1]);
			// 候选4:max(A_i - A_{i-1})
			for (int i = 1; i < n; i++) {
				ans = Math.max(ans, a[i] - a[i - 1]);
			}
			sb.append(ans).append('\n');
		}
		System.out.print(sb.toString());
	}
}
        题目内容
远古风语者在风之谷留下了一串符文,每个符文刻录着能量强度,记作 A1,A2,...,An ;
他定义这串符文的 平滑度 为 S(A)=∑i=1n−1(Ai−Ai+1)
现风语者可对一段连续符文区间施展 轮回咒,即对区间 [l,r] 进行一次或多次 循环右移:
- 每次循环右移一步将符文 Ar ,移至位置 l ,其余元素依次后移;
 
恰好施展一次轮回咒后,得到新的符文序列 A′ 。请问能获得的最大平滑度 max S(A′) 是多少?
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≤T≤104) ,表示测试组数;
除此之外,保证所有测试数据的 n 之和不超过 2×105 。
输出描述
对于每组测试数据,新起一行输出一个整数,表示恰好执行一次轮回咒后能达到的最大平滑度。
样例1
输入
2
3
1 2 3
4
1 4 2 3
输出
1
3
说明
第一个样例中,将全段 [1,3] 右移一步得到 {3,1,2} ,平滑度 (3−1)+(1−2)=1 ;
第二个样例中,将区间 [1,4] 右移三步得到 {4,2,3,1} ,平滑度 (4−2)+(2−3)+(3−1)=3 。