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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Codeforces Round #702 (Div. 3)解题报告

發布時間:2024/7/5 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Round #702 (Div. 3)解题报告 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Codeforces Round #702 (Div. 3) 全部題解

讀錯題意,寫了半天真是心態爆炸,總的來看這次題目不難的。

A. Dense Array

http://codeforces.com/contest/1490/problem/A

解題思路
相鄰的數字必然是倘若不滿足的話是需要插入數據的,那么我們模擬插入數據即可.
x=min(ai,ai+1),y=max(ai,ai+1)x = min(a_i, a_{i+1}), y = max(a_i, a_{i+1})x=min(ai?,ai+1?),y=max(ai?,ai+1?)

  • 倘若2?x≤y2 * x \leq y2?xy不需要操作
  • 否則,需要插入數據。不斷的貪心插入 2?x2\cdot x2?x,直到滿足條件。 其實這有一個公式的,推導與公式如下所示。

    模擬乘以2
#include <bits/stdc++.h> using namespace std;typedef long long LL; typedef pair<int, int> PII; const int N = 1010, INF = 0x3f3f3f3f; int n, a[N]; PII b[N]; bool st[N];int cal(int t1, int t2) {int ret = 0;while (2 * t1 < t2){ret ++;t1 *= 2;}return ret; }int main() {int t; cin >> t;while (t -- ){cin >> n;LL x = 0;for (int i = 1; i <= n; i ++ ){scanf("%d", &a[i]);}double cnt;for (int i = 1, t1, t2; i < n; i ++ ){t1 = min(a[i], a[i + 1]), t2 = max(a[i], a[i + 1]);if (t1 * 2 >= t2) continue;else{x += cal(t1, t2);}}cout << x << endl;}return 0; }

直接上公式,沒有過,應該是小數精度會被卡

#include <bits/stdc++.h> using namespace std;typedef long long LL; typedef pair<int, int> PII; const int N = 1010, INF = 0x3f3f3f3f; int n, a[N];int main() {int t; cin >> t;while (t -- ){cin >> n;LL x = 0;for (int i = 1; i <= n; i ++ ){scanf("%d", &a[i]);}double cnt;for (int i = 1, t1, t2; i < n; i ++ ){t1 = min(a[i], a[i + 1]), t2 = max(a[i], a[i + 1]);if (t1 * 2 >= t2) continue;else{x += ceil(log(t2 * 1.0 / t1) / log(2)) - 1;}}cout << x << endl;}return 0; }

B. Balanced Remainders

http://codeforces.com/contest/1490/problem/B

先統計出來%3\%3%3余數為0,1,20,1, 20,1,2數字的數量c0,c1,c2c_0, c_1, c_2c0?,c1?,c2?,根據倘若多,那么一定會送走,倘若少,一定會挪進行這個性質進行模擬,而且對于特定的cic_ici?他給別人,或者是別人給他的交易對象是一樣的,即操作是固定的。

#include <bits/stdc++.h> using namespace std;typedef long long LL; typedef pair<int, int> PII; const int N = 100010, INF = 0x3f3f3f3f; int n, a[N]; int c[5] = {0, 0, 0};int opt(int idx, int ave) {int idx2 = (idx + 1) % 3, idx0 = (idx - 1 + 3) % 3;int need = 0;if (c[idx] < ave) // 過少,需要向前一個索要{need = ave - c[idx];c[idx0] -= need;c[idx] += need;}else // 太多,需要給下一個{need = c[idx] - ave;c[idx2] += need;c[idx] -= need;}return need; }int main() {int t; cin >> t;while (t -- ){cin >> n;int ave = n / 3;memset(c, 0, sizeof c);for (int i = 1; i <= n; i ++ ){scanf("%d", &a[i]);c[a[i] % 3] ++;}int res = 0;for (int i = 0; i < 3; i ++ ){res += opt(i, ave);}printf("%d\n", res);}return 0; }

C. Sum of Cubes

http://codeforces.com/contest/1490/problem/C

直接就是 將 i3i^3i3在map上進行打表就可以了。
很關鍵的是預處理多處理幾個,不然很容易被卡

#include <bits/stdc++.h> using namespace std;typedef long long LL; const int N = 100010; LL n; LL a[N]; map<LL, bool> m;int main() {int t; cin >> t;for (LL i = 1; i <= 10010; i ++ ) // 這里僅僅寫到 10000就會 WA,主要是怕他多往后走了一步,查詢到了0{a[i] = i * i * i;m[a[i]] = true;}// cout << m[0] << endl;while (t -- ){scanf("%lld", &n);bool flag = false;LL surp;for (int i = 1; !flag && a[i] <= n; i ++ ){surp = n - a[i];if (m[surp] == true){flag = true;}}if (flag) puts("YES");else puts("NO");}return 0; }

D. Permutation Transformation

http://codeforces.com/contest/1490/problem/D


一個簡單的模擬dfs,每次在區間找最大值作為 root 即可

#include <bits/stdc++.h> using namespace std;const int N = 110; int a[N], n, depth[N];void build(int fa, int l, int r) {if (l >= r) return;int u = -1, v = -1;// 左子樹for (int i = l; i < fa; i ++ ){if (u == -1 || a[u] < a[i])u = i;}depth[u] = depth[fa] + 1;build(u, l, fa - 1);// 右子樹for (int i = fa + 1; i <= r; i ++ ){if (v == -1 || a[v] < a[i])v = i;}depth[v] = depth[fa] + 1;build(v, fa + 1, r); }int main() {int t; cin >> t;while (t -- ){scanf("%d", &n);for (int i = 1; i <= n; i ++ )scanf("%d", &a[i]);memset(depth, -1, sizeof depth);int v;for (int i = 1; i <= n; i ++ ){if (a[i] == n){v = i;break;}}depth[v] = 0;build(v, 1, n);cout << depth[1];for (int i = 2; i <= n; i ++ )printf(" %d", depth[i]);cout << endl;}return 0; }

E. Accidental Victory

http://codeforces.com/contest/1490/problem/E

說白了就是看誰可以贏。
首先我們先將他們按照各自的數值排序,得到數組a1,a2???,ana_1,a_2\cdot\cdot\cdot,a_na1?,a2????,an?,對應編號為idx1,idx2,???,idxnidx_1, idx_2, \cdot\cdot\cdot,idx_nidx1?,idx2?,???,idxn?,我們對數組求取前綴和sum1,sum2,???,sumnsum_1, sum_2,\cdot\cdot\cdot,sum_nsum1?,sum2?,???,sumn?
我們從后往前看,

  • nnn個是最大的,肯定有機會成為winner
  • n?1n-1n?1倘若可以成為winnerwinnerwinner,當且僅當他贏過1n?21~n-21?n?2個人,然后和ana_nan?比較,倘若他成不了winnerwinnerwinner那么直接算法結束,比他小的人更成為不了winnnerwinnnerwinnner
  • 不斷這樣算下去即可
#include <bits/stdc++.h> using namespace std;typedef long long LL; typedef pair<LL, int> PII; const int N = 200010; vector<int> res; LL a[N]; LL b[N]; PII c[N]; int n;bool cmp(const PII &t1, const PII &t2) {return t1.first < t2.first; } int main() {int t; cin >> t;while (t -- ){scanf("%d", &n);for (int i = 1; i <= n; i ++ ){scanf("%lld", &a[i]);c[i].first = a[i];c[i].second = i;}sort(c + 1, c + n + 1, cmp);for (int i = 1; i <= n; i ++ )b[i] = b[i - 1] + c[i].first;res.clear();res.push_back(c[n].second);for (int i = n - 1; i >= 1; i -- ){if (b[i] >= c[i + 1].first)res.push_back(c[i].second);elsebreak;}sort(res.begin(), res.end());cout << res.size() << endl;cout << res[0];for (int i = 1; i < res.size(); i ++ )printf(" %d", res[i]);cout << endl;}return 0; }

F. Equalize the Array

http://codeforces.com/contest/1490/problem/F

具體思路:
先用map將出現次數存儲起來,統計出出現次數為iii的數字一共有cnticnt_icnti?個,
那么我們首先模擬一下,想讓所有數字出現的次數為iii或者是000,那么我們需要將出現次數小于等于iii的數字全部移除,需要的次數為cnt1?1+???cnti?1?(i?1)cnt_1\cdot1+\cdot\cdot\cdot cnt_{i-1}\cdot{(i-1)}cnt1??1+???cnti?1??(i?1)
需要將出現次數大于iii的數字次數縮減為iii
需要的操作次數為$$
?(i+1)?cnti+1+(i+2)?cnti+2+???+(n)?cntn?i?(cnti+1+cnti+2+???+cntn)\Longrightarrow(i+1)\cdot cnt_{i+1} + (i+2)\cdot cnt_{i+2}+\cdot\cdot\cdot+(n)\cdot cnt_n -i\cdot(cnt_{i+1}+cnt_{i+2}+\cdot\cdot\cdot+cnt_n)?(i+1)?cnti+1?+(i+2)?cnti+2?+???+(n)?cntn??i?(cnti+1?+cnti+2?+???+cntn?)
因此我們直接預處理出來 cnticnt_icnti?的前綴數組和他們的加權成前綴數組即可

#include <bits/stdc++.h> using namespace std;typedef pair<int, int > PII; typedef long long LL; const int INF = 0x3f3f3f3f; const int N = 200010; int a[N + 5]; int n; map<int, int> m; int cnt[N + 5]; int sum[N + 5]; LL addval[N + 5];int main() {int t; cin >> t;while (t -- ){m.clear();scanf("%d", &n);for (int i = 1; i <= n; i ++ ){scanf("%lld", &a[i]);m[a[i]] ++;}memset(cnt, 0, sizeof cnt);memset(sum, 0, sizeof sum);memset(addval, 0, sizeof addval);map<int, int>::iterator it;for (it = m.begin(); it != m.end(); it ++) // 出現it->second 次數的數字進行統計{/// printf("IT: %d, %d\n", it->first, it->second);cnt[it->second] ++;}// 計算前綴數組和累加和數組for (int i = 1; i <= n; i ++ ) // 最多出現 n 次{sum[i] = sum[i - 1] + cnt[i];addval[i] = addval[i - 1] + LL(cnt[i]) * i;} /*printf("CNT:\n\t");for (int i = 1; i <= n; i ++ ){printf("%d ", cnt[i]);}cout << endl; */LL res = 1e16;LL up, down;for (int i = 1; i <= n; i ++ ){down = addval[i - 1];up = (addval[n] - addval[i - 1]) - (sum[n] - sum[i - 1]) * i;res = min(res, up + down);}cout << res << endl;}return 0; }

G. Old Floppy Drive

http://codeforces.com/contest/1490/problem/G


本題是一個較為隱蔽的二分題目,需要我們貪心預處理出來可以二分的數組。
首先我們先將前綴數組給求出來,
并且貪心得到 cnt不斷增加,而且前綴和也增加的數字,將其放入數組v, 具體見代碼max_val部分。
那么數組 v 是一個數值(無論是val,還是opt_cnt)都不斷增加的數據

  • 倘若 xix_ixi?在 數組 v 最大值的范圍之內,那么直接二分找最小的cnt
  • 否則,需要判斷一下整個原數組 a 的累加和是否大于零,倘若小于等于0,無解
  • 否則,是可以經過不斷的循環找到這個數的,首先我們根據max(v)找到最小的循環次數,然后二分即可。
    本題最坑的點就是 long long 開的地方很多,幾乎所有的數據都要開long long
#include <bits/stdc++.h> using namespace std;typedef long long LL; const LL INF = 0x3f3f3f3f3f3f3f3f; const int N = 200010; int n, m; LL a[N], x[N]; LL sum[N]; class Node { public:LL val, cnt;Node(LL _val = 0, LL _cnt = 0){val = _val, cnt = _cnt;} }b[N];int main() {int t; cin >> t;while (t -- ){cin >> n >> m;LL cur_max = -INF;b[1] = Node(-INF, -1);int n2 = 1;sum[0] = 0LL;for (int i = 1; i <= n; i ++ ){scanf("%lld", &a[i]);sum[i] = sum[i - 1] + a[i];if (sum[i] > cur_max){cur_max = sum[i];b[++ n2] = Node(cur_max, i - 1); // 注意在這里的 - 1}}for (int i = 1; i <= m; i ++ )scanf("%lld", &x[i]);// 當前的 b 數字 是 1~n val 增加, cnt增加的遞增數組,下面我們的 x 僅僅只需要二分即可;/// printf("RES:\n\t");LL loop = sum[n];for (int i = 1; i <= m; i ++ ){if (b[n2].val >= x[i]) // 可以直接二分找 >= x[i] 的最小值{int l = 1, r = n2, mid;while (l < r){mid = l + r >> 1;if (b[mid].val >= x[i])r = mid;elsel = mid + 1;}printf("%lld ", b[l].cnt);}else // 查看他的 loop{if (loop <= 0) // 無法達到{printf("-1 ");}else{LL loopcnt = (x[i] - b[n2].val) / loop + ((x[i] - b[n2].val) % loop != 0);x[i] -= loopcnt * loop;int l = 1, r = n2, mid;while (l < r){mid = l + r >> 1;if (b[mid].val >= x[i])r = mid;elsel = mid + 1;}printf("%lld ", b[l].cnt + loopcnt * n); // loopcnt 是乘以 n 的}}}puts("");}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Codeforces Round #702 (Div. 3)解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。

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