日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2013 ACM/ICPC 长沙网络赛J题

發布時間:2023/12/31 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2013 ACM/ICPC 长沙网络赛J题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:一個數列,給出這個數列中的某些位置的數,給出所有相鄰的三個數字的和,數列頭和尾處給出相鄰兩個數字的和。有若干次詢問,每次問某一位置的數字的最大值。

分析:設數列為a1~an。首先通過相鄰三個數字的和我們可以求出a3,a6,a9……是多少。a3=sum(a1,a2,a3)-sum(a1,a2)。a6=sum(a4,a5,a6)-sum(a3,a4,a5)。后面依次類推。

推到了數列的最右面,如果恰好知道了an或者a(n-1)中的一個,那么可以通過sum(an,a(n-1))減去它來求得另一個。

這個題還有個性質就是,只要知道數列中連續的兩位就可以通過不斷向兩側延伸的方法得到整個數列。因為任意相鄰三個的和都知道,知道其中兩個數自然可以得到第三個。

所以我們如果知道了最后兩位則一定可以知道整個數列。同樣如果根據已知的數列中的數和推出的數能得知兩個已知的相鄰的數的話,也可推出整個數列。

唯一一種無法確定該數列的情況就是我們,沒有推出最后的兩個數(即n%3==2的情況),且數列中已知給出的數也沒有提供任何推出信息以外的信息。

這時我們就獲得了一個不確定的數列,將數列中的數字ai按照i%3結果的不同分成三組,得0則已知。

得1的數之間互相是同增同減的,因為他們互相之間的差是一樣的。a1-a4=sum(a1,a2,a3)-sum(a2,a3,a4)。得2的同理。所以這些同增同減的數字會同時取得最大值或最小值。

得1和得2的之間是此消彼漲的,因為他們互相之間的和是一樣的。a1+a2=sum(a1,a2) ? ?a2+a4=sum(a2,a3,a4)-a3 ? ?a4+a5=sum(a3,a4,a5)-a3 所以得1的取得最小值則得2的取得最大值,反之亦然。

在符合了這些和與差的條件之后,唯一會導致數列不合法的情況就是出現負數。我們只需要先對得1的隨意娶個值,并推出整個數列后,根據最小數值調整所有得1的取值,使最小的那個數恰好為0。

這樣就可以使得1的取最小值,即讓得2的取得最大值。

同理可以求得得1的最大值。

存儲好各種最大值之后按題目中的詢問輸出即可。計算最大值需要O(n),每次詢問需要O(1),共m次詢問,總復雜度為O(n + m)。

#include <cstring> #include <algorithm> #include <cstdio> using namespace std;#define MAX_NUM 100005int array[MAX_NUM], array1[MAX_NUM], array2[MAX_NUM]; int sum[MAX_NUM]; int num; int query_num; bool filled;void cal_left(int pos, int array[]) {for (int i = pos - 2; i > 0; i--)array[i] = sum[i + 1] - array[i + 1] - array[i + 2]; }void cal_right(int pos, int array[]) {for (int i = pos + 2; i <= num; i++)array[i] = sum[i - 1] - array[i - 1] - array[i - 2]; }void input() {int pos = -1;for (int i = 1; i <= num; i++){scanf("%d", &array[i]);if (i % 3 != 0 && array[i] != -1)pos = i;}for (int i = 1; i <= num; i++)scanf("%d", &sum[i]);array[0] = 0;for (int i = 3; i <= num; i += 3)array[i] = sum[i - 1] - (sum[i - 2] - array[i - 3]);if (num % 3 == 2 && pos == -1)return;filled = true;if (array[num] != -1)array[num - 1] = sum[num] - array[num];if (array[num - 1] != -1)array[num] = sum[num] - array[num - 1];if (array[num] != -1)cal_left(num, array);array[num + 1] = 0;if (pos != -1){if (array[pos - 1] != -1)pos--;cal_left(pos + 1, array);cal_right(pos, array);} }void work() {scanf("%d", &query_num);for (int i = 0; i < query_num; i++){int a;scanf("%d", &a);a++;if (filled){printf("%d\n", array[a]);continue;}if (a % 3 == 1)printf("%d\n", array1[a]);else if (a % 3 == 2)printf("%d\n", array2[a]);elseprintf("%d\n", array[a]);} }void make2() {memcpy(array2, array, sizeof(array2));array2[1] = 0;array2[2] = sum[1] - array2[1];cal_right(1, array2);array2[1] -= *min_element(array2 + 1, array2 + num + 1);array2[2] = sum[1] - array2[1];cal_right(1, array2); }void make1() {memcpy(array1, array, sizeof(array1));array1[num] = 0;array1[num - 1] = sum[num] - array1[num];cal_left(num, array1);array1[num] -= *min_element(array1 + 1, array1 + num + 1);array1[num - 1] = sum[num] - array1[num];cal_left(num, array1); }int main() {while (scanf("%d", &num) != EOF){filled = false;input();if (!filled){make2();make1();}work();}return 0; } View Code

?

轉載于:https://www.cnblogs.com/rainydays/p/3334641.html

總結

以上是生活随笔為你收集整理的2013 ACM/ICPC 长沙网络赛J题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。