1. 程式人生 > >NOIP2018龍虎鬥

NOIP2018龍虎鬥

龍虎鬥 軒軒和凱凱正在玩一款叫《龍虎鬥》的遊戲,遊戲的棋盤是一條線段,線段上有 n個兵營(自左至右編號 1 ~ n),相鄰編號的兵營之間相隔 1 釐米,即棋盤為長度為n − 1 釐米的線段。i號兵營裡有ci位工兵。 軒軒在左側,代表“龍”;凱凱在右側,代表“虎”。 他們以 m 號兵營作為分界,靠左的工兵屬於龍勢力,靠右的工兵屬於虎勢力,而第 m號兵營中的工兵很糾結,他們不屬於任何一方。

一個兵營的氣勢為:該兵營中的工兵數 × 該兵營到 m號兵營的距離;參與遊戲一方的勢力定義為:屬於這一方所有兵營的氣勢之和。

下面圖 2 為 n = 6,n= 4 的示例,其中紅色為龍方,黃色為虎方:

遊戲過程中,某一刻天降神兵,共有 s1 位工兵突然出現在了 p1 號兵營。作為軒軒和凱凱的朋友,你知道如果龍虎雙方氣勢差距太懸殊,軒軒和凱凱就不願意繼續玩下去了。為了讓遊戲繼續,你需要選擇一個兵營p2 ,並將你手裡的 s2 位工兵全部派往兵營 p2 ,使得雙方氣勢差距儘可能小。

注意:你手中的工兵落在哪個兵營,就和該兵營中其他工兵有相同的勢力歸屬(如果落在 m 號兵營,則不屬於任何勢力)。 輸入

輸入檔案的第一行包含一個正整數n,代表兵營的數量。 接下來的一行包含n個正整數,相鄰兩數之間以一個空格分隔,第i個正整數代 表編號為i的兵營中起始時的工兵數量 di 。 接下來的一行包含四個正整數,相鄰兩數間以一個空格分隔,分別代表m,p1 ,s1 ,s2 。

輸出

輸出檔案有一行,包含一個正整數,即 p2 ,表示你選擇的兵營編號。如果存在多個編號同時滿足最優,取最小的編號。

樣例輸入

(如果複製到控制檯無換行,可以先貼上到文字編輯器,再複製)

【輸入樣例 1】 6 2 3 2 3 2 3 4 6 5 2 【輸入樣例 2】 6 1 1 1 1 1 16 5 4 1 1

樣例輸出

【輸出樣例 1】 2 【輸出樣例 2】 1

提示

【輸入輸出樣例 1 說明】

見問題描述中的圖 2。

雙方以 n = 4 號兵營分界,有 s1 = 5 位工兵突然出現在 p1 = 6 號兵營。

龍方的氣勢為:

2 × (4 − 1) + 3 × (4 − 2) + 2 × (4 − 3) = 14

虎方的氣勢為:

2 × (5 − 4) + (3 + 5) × (6 − 4) = 18

當你將手中的 s2 = 2 位工兵派往 p2 = 2 號兵營時,龍方的氣勢變為:

14 + 2 × (4 − 2) = 18

此時雙方氣勢相等。

【輸入輸出樣例 2 說明】

雙方以 n = 5 號兵營分界,有 s1 = 1 位工兵突然出現在 p1 = 4 號兵營。

龍方的氣勢為:

1 × (5 − 1) + 1 × (5 − 2) + 1 × (5 − 3) + (1 + 1) × (5 − 4) = 11

虎方的氣勢為:

16 × (6 − 5) = 16

當你將手中的 s2 = 1 位工兵派往 p2 = 1 號兵營時,龍方的氣勢變為:

11 + 1 × (5 − 1) = 15

此時可以使雙方氣勢的差距最小。

【資料規模與約定】

1 < m < n,1 ≤ p1 ≤ n。

對於20%的資料,n = 3, m = 2, ci = 1, s1,s2 ≤ 100。

另有20%的資料, n ≤ 10, p1 = m, ci = 1, s1,s2 ≤ 100。

對於20%的資料,n = 3, m = 2, ci = 1,s1,s2 ≤ 100。

對於60%的資料, n ≤ 100, ci = 1,s1,s2 ≤ 100。

對於80%的資料, n ≤ 100, ci,s1,s2 ≤ 100。

對於100%的資料, n ≤ 10^5, ci = 1, s1,s2 ≤ 10^9。

/*
民間資料80分版 
#include <cstdio>
#include <iostream>
#define LL_ long long
using namespace std;
   
const int MAXN_ = 100005;
   
void Read_(LL_ &wo_X) {
    LL_ wo_F = 1;
    wo_X = 0;
    char wo_C = getchar();
    while(wo_C < '0' || wo_C > '9') {
        if (wo_C == '-') {
            wo_F = -1;
        }
        wo_C = getchar();
    }
    while(wo_C >= '0' && wo_C <= '9') {
        wo_X = (wo_X << 3) + (wo_X << 1) + wo_C - '0';
        wo_C = getchar();
    }
    wo_X *= wo_F;
}
   
LL_ PutOut_(LL_ X) {
    if (X < 0)  {
        X = (~X) + 1;
        putchar('-');
    }
    if (X > 9) {
        PutOut_(X / 10);
    }
    putchar(X % 10 + 48);
}
   
LL_ Fabs_(LL_ wo_X) {
    if (wo_X < 0) 
        wo_X = (~wo_X) + 1;
    return wo_X;
}
   
LL_ wo_N ,wo_A[MAXN_] ,wo_Index = 0,wo_M ,wo_P1 ,wo_s1,wo_s2 ,X_Sum = 0 ;
LL_ K_Sum = 0 ,MINN = 0x3f3f3f3f3f3f3f3f;
   
int main() {
//  freopen("fight.in","r",stdin);
//  freopen("fight.out","w",stdout);
    Read_(wo_N);
    for (LL_ i = 1 ; i <= wo_N ; i ++ ) {
        Read_(wo_A[i]);
    }                           
    Read_(wo_M);
    Read_(wo_P1);
    Read_(wo_s1);
    Read_(wo_s2);
    wo_A[wo_P1] += wo_s1;
    for (LL_ i = 1 ; i < wo_M ; i ++ ) X_Sum += wo_A[i] * (wo_M - i);    
    for (LL_ i = wo_M + 1 ; i <= wo_N ; i ++ ) K_Sum += wo_A[i] * (i - wo_M);
    if(X_Sum < K_Sum) {
        for (LL_ p = 1 ; p < wo_M ; p ++ ) {
             if (Fabs_(Fabs_(X_Sum + (Fabs_(wo_M - p) * wo_s2)) - K_Sum) < MINN) {
                MINN = Fabs_(Fabs_(X_Sum + (Fabs_(wo_M - p) * wo_s2)) - K_Sum);
                wo_Index = p;
            }
        }
    }
    else if(X_Sum > K_Sum) {
        for (LL_ p = wo_M + 1 ; p <= wo_N ; p ++ ) {
            if (Fabs_(Fabs_(K_Sum + (Fabs_(wo_M - p) * wo_s2)) - X_Sum) < MINN) {
                MINN = Fabs_(Fabs_(K_Sum + (Fabs_(wo_M - p) * wo_s2)) - X_Sum);
                wo_Index = p;
            }
        }
    }
    PutOut_(wo_Index);
    return 0; 
}
*/
//正解 
#include <cstdio>
const int N=1e5+5;
int n,m,p1;
long long c[N],s1,s2;
  
int main() {
    //freopen("fight.in","r",stdin);
    //freopen("fight.out","w",stdout);
      
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) {
        scanf("%lld",&c[i]);//輸入
    }
    scanf("%d %d %lld %lld",&m,&p1,&s1,&s2);
    c[p1]+=s1;
    long long sum=0,minn=1LL<<62;//預處理
      
    for(int i=1; i<=n; ++i) {
        sum+=(i-m)*c[i];//統計虎的氣勢
    }
      
    int ans=m;
    for(int i=1; i<=n; ++i) {//一重迴圈遍歷,遍歷每個點,並將選中的這個點增加對應的氣勢值,並比較最小值
        long long now=sum+(i-m)*s2;//增加氣勢值
        if(now<0) {
            now=(~now); //注意這裡不要加一 
        }
        if(now<minn) {
            minn=now;
            ans=i;//記錄下標
        }
    }
    printf("%d\n",ans);//輸出結果
      
    return 0;
}