【タイトル】サイオニックトランスミッション(欲張りアルゴリズム、ブルーブリッジカップ)
今回は、第10回ブルーブリッジカップC / C ++とJavaグループBの州大会の最後のトピックを見ていきます。
トピックが少し長いので、トピックの一部だけをここに示します。
図に示すように、質問の最後に、質問の入力量が比較的多く、すばやく読み込む必要があることを思い出させます。Javaプレーヤーの場合は、簡単な入力を作成することをお勧めします。タイムアウトを回避するためのクラス。
この質問のデータの範囲に応じて、高速入力クラスでlong型とint型のデータ入力メソッドを作成する必要がある場合があります。
コードは次のように表示されます。
class JavaIn {
static private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static private StringTokenizer sti = null;
//long数组快速输入
public static void in(long[] arr) {
int len = arr.length;
//这里特殊处理一下,从1开始输入
for (int i = 1; i < len; i++) {
arr[i] = nextLong();
}
}
public static String next() {
while (sti == null || !sti.hasMoreTokens()) {
try {
sti = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return sti.nextToken();
}
public static long nextLong() {
return Long.parseLong(next());
}
public static int nextInt(){
return Integer.parseInt(next());
}
}
このメソッドを入出力に使用すると、Scannerクラスよりも効率的ですが、文字や数字などのデータしか読み取れないという欠点があります。もちろん、この質問には適していますが、他のトピックについては、料金を支払う必要があります。データ入力のタイプに注意してください。
この質問の分析を始めましょう。質問は比較的長いですが、質問の核となる内容を把握する必要があります。「正式には、ai-1 + = ai、ai + 1 + = ai、ai- = 2aiです」および「最小の不安定性」「最初のテストケースの最初の文、「5、-2、3」(ai-1 = 5、ai + 1 = 3、ai = -2)などのこれらの2つの文タイトルの操作に後で、それはなりました:
a [i-1] = 5 +(-2)= 3
a [i + 1] = 3 +(-2)= 1
a [i] = -2-(-2)* 2 = 2
これが最初の例の説明です。このグループのケースは非常に特殊です。高レベルのテンプル騎士団は3つしかありません。それ以上あると、うまく処理できません。
これには、接頭辞と知識が必要です。
接頭辞の合計は、配列が特定の添え字を記録する前の別の配列のすべての要素の合計です。つまり、配列a = [0,1,2]であり、
その接頭辞と配列bがb [0]を満たすと仮定します。= a [0] = 0、b [1] = a [0] + a [1] = 2…
もちろん、これは1次元のプレフィックスの合計にすぎません。この問題については、一次元しか理解できません。
この質問に戻って、今学んだ接頭辞と知識を使用して、質問の高レベルテンプル騎士団の超常的パワーの接頭辞の合計である配列aをsに設定し、次にs [i-1]に設定します。 = a [0] +…+ A [i-1]; s [i] = a [0] +…+ a [i]; s [i + 1] = a [0] +…+ a [i + 1]。
特別なs [0] = a [0]
最初のテストケースで、すべてのaを並べ替える場合、すべてのプレフィックスと隣接する2つのプレフィックスの差の絶対値の最大値を最小にする必要があることを思い出させるのは難しいことではありません。
以下は完全なコード実装です(いくつかの詳細はコメントにあります):
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class T10_灵能传输 {
public static void main(String[] args) {
int T;
T = JavaIn.nextInt();
while (T-- != 0) {
int n = JavaIn.nextInt();
long[] a = new long[n + 1];
//前缀和
long[] s = new long[n + 1];
long ans = 0;
JavaIn.in(a);
s[0] = 0;
for (int i = 1; i <= n; i++) {
s[i] = s[i - 1] + a[i];
}
long s_0 = s[0];
long s_n = s[n];
if (s_0 > s_n) {
long t = s_0;
s_0 = s_n;
s_n = t;
}
Arrays.sort(s);
for (int i = 0; i <= n; i++) {
if (s_0 == s[i]) {
s_0 = i;
break;
}
}
for (int i = 0; i <= n; i++) {
if (s_n == s[i]) {
s_n = i;
break;
}
}
//建立标记数组,避免处理奇偶问题
boolean[] marks = new boolean[n + 1];
int leftPtr = 0;
int rightPtr = n;
//储存传递完的灵能
long[] ss = new long[n + 1];
//跳着取
for (int i = (int) s_0; i >= 0; i -= 2) {
ss[leftPtr++] = s[i];
//标记
marks[i] = true;
}
for (int i = (int) s_n; i <= n; i += 2) {
ss[rightPtr--] = s[i];
//标记
marks[i] = true;
}
for (int i = 0; i <= n; i++) {
//没被标记的就存储起来
if (!marks[i]) {
ss[leftPtr++] = s[i];
}
}
for (int i = 1; i <= n; i++) {
ans = Math.max(ans, Math.abs(ss[i] - ss[i - 1]));
}
System.out.println(ans);
}
}
}
class JavaIn {
static private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static private StringTokenizer sti = null;
//long数组快速输入
public static void in(long[] arr) {
int len = arr.length;
//这里特殊处理一下,从1开始输入
for (int i = 1; i < len; i++) {
arr[i] = nextLong();
}
}
public static String next() {
while (sti == null || !sti.hasMoreTokens()) {
try {
sti = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return sti.nextToken();
}
public static long nextLong() {
return Long.parseLong(next());
}
public static int nextInt() {
return Integer.parseInt(next());
}
}
提出後の結果:
要約すると、このトピックのいくつかの戦略は本当に考えるのが難しいです。私はより料理が好きで、大物のアイデアを参照することでそれを書くことができます。