Codeforces Round #529 (Div. 3) 題解

生病康復中,心情很很差,下午回蘇州,你在藍橋杯,但願你別寫錯了。c++

刷了一套題散散心,Div 3,所有是 1 A,感受比之前慢了好多好多啊。數組

這幾天也整理了一下本身要作的事情,工做上要努力... ... 晚上仍是要認認真真背英語的。機器學習

找了幾個同窗問了一下,有點想本身作點 project 了,再學學機器學習,深度學習之類的,弄點小 AI project 玩玩吧... ...沒事看點各類科技新聞開開眼界。學習

 

題目連接spa

 

A - Repeating Ciphercode

挺簡單的,只要知道哪幾個位置要輸出就能夠了。blog

時間複雜度:$O(N)$隊列

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
char s[maxn], len;

int main() {
  scanf("%d", &len);
  scanf("%s", s);
  int p = 0;
  for(int i = 0; i < len; i = i + p) {
    printf("%c", s[i]);
    p++;
  }
  printf("\n");
  return 0;
}

  

B - Array Stabilizationip

不是刪原數組中的最小值就是刪最大值。get

時間複雜度:應該是能夠 $O(N)$ 實現的吧,可是排個序 $O(N*logN)$ 寫起來多簡單。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
int a[maxn], n;

int main() {
  scanf("%d", &n);
  for(int i = 1; i <= n; i ++) {
    scanf("%d", &a[i]);
  }
  sort(a + 1, a + 1 + n);
  printf("%d\n", min(a[n - 1] - a[1], a[n] - a[2]));
  return 0;
}

  

C - Powers Of Two

先將 $N$ 轉換成二進制,若是不到 $k$ 個,那麼能夠找一個數字出來,除以 $2$,拆成兩個,這樣就多了一個,按這樣慢慢操做就行了。

時間複雜度:在實現的時候我把全部數字扔進了優先隊列,每次拆最大的那個,事實上每次拆一個可拆的就能夠了。$O(K*logK)$。

#include <bits/stdc++.h>
using namespace std;

int n, k;

priority_queue<int> Q;

int cnt_Q;

int main() {
  scanf("%d%d", &n, &k);
  for(int i = 29; i >= 0; i --) {
    if(n >= (1 << i)) {
      Q.push(i);
      cnt_Q ++;
      n -= (1 << i);
    }
  }

  if(cnt_Q > k) {
    printf("NO\n");
    return 0;
  }

  while(cnt_Q < k) {
    int tp = Q.top();
    if(tp == 0) {
      printf("NO\n");
      return 0;
    }

    Q.pop();

    Q.push(tp - 1);
    Q.push(tp - 1);

    cnt_Q ++;
  }

  printf("YES\n");
  while(!Q.empty()) {
    int tp = Q.top();
    printf("%d ", 1 << tp);
    Q.pop();
  }

  return 0;
}

  

D - Circular Dance

這題比較逗,數據保證必定有解。emmmm... 那是否是很大機率填完就是可行解呢?我也不太會證實,反正這樣寫了一下就 AC 了,寫以前就挺有把握。

複雜度多是線性的?

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 10;

int n;
int a[maxn];

int b[maxn][5];

int flag;

void dfs(int x) {

  int num1 = b[a[x]][1];
  int num2 = b[a[x]][2];

  if(b[num1][1] == num2 || b[num1][2] == num2) {
    a[x + 1] = num1;
    a[x + 2] = num2;

    if(x == n - 2) {
      flag = 1;
      return;
    }

    dfs(x + 1);
    if(flag) return;
  }

  if(b[num2][1] == num1 || b[num2][2] == num1) {
    a[x + 1] = num2;
    a[x + 2] = num1;

    if(x == n - 2) {
      flag = 1;
      return;
    }

    dfs(x + 1);
    if(flag) return;
  }
}

int main() {
  scanf("%d", &n);
  for(int i = 1; i <= n; i ++) {
    scanf("%d%d", &b[i][1], &b[i][2]);
  }

  flag = 0;
  a[1] = 1;
  dfs(1);

  for(int i = 1; i <= n; i ++) {
    printf("%d ", a[i]);
  }
  printf("\n");

  return 0;
}

 

E - Almost Regular Bracket Sequence

這個題意是,問你有幾個位置,只改變這個位置,能讓它變成合法括號匹配串。

括號匹配常見套路。左括號變成 1,右括號變成 -1,算前綴和 $S_i$。

一個合法的括號匹配串的充要條件是:[1] 對於任何 $i$, $S_i$ 都非負。[2] $S_n = 0$。

balabalabala.....

而後你大概就會作了。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;

int n;
int a[maxn], b[maxn], c[maxn];
char s[maxn];

int main() {
  scanf("%d", &n);
  scanf("%s", s);
  for(int i = 1; i <= n; i ++) {
    a[i] = (s[i - 1] == '(') ? 1 : -1;
  }
  for(int i = 1; i <= n; i ++) {
    a[i] += a[i - 1];
  }

  c[1] = a[1];
  for(int i = 2; i <= n; i ++) {
    c[i] = min(a[i], c[i - 1]);
  }

  b[n] = a[n];
  for(int i = n - 1; i >= 1; i --) {
    b[i] = min(a[i], b[i + 1]);
  }

  for(int i = 1; i <= n; i ++) {
   // printf("[i: %d]  a: %d, b: %d, c: %d\n", i, a[i], b[i], c[i]);
  }

  int ans = 0;
  for(int i = 1; i <= n; i ++) {
    if(s[i - 1] == '(') {
      if(c[i - 1] >= 0 && b[i] - 2 >= 0 && a[n] - 2 == 0) ans ++;
    } else {
      if(c[i - 1] >= 0 && b[i] + 2 >= 0 && a[n] + 2 == 0) ans ++;
    }
  }

  printf("%d\n", ans);

  return 0;
}

  

F - Make It Connected

這個最小生成樹還挺好玩。摸索了半天才知道啊。。果真洞察力減弱了。

就是兩種邊,一種讀入的邊,另外一種原來就有的邊,每次怎麼取呢?

突破口是樣例 2,先看看 $m$ 是 0 的時候要怎麼弄?也就是全是原來的邊的時候答案是怎麼來的。

畫畫圖就能知道是哪些邊了... ... 我就不寫了。

$m$ 不是 0 的時候,那豈不是就是把這些邊和讀入的邊合起來作個 MST 嗎...

The world is so funny, but I am so naive

#include <bits/stdc++.h>
using namespace std;

const int maxn = 4e5 + 10;
struct Edge {
  int x, y;
  long long w;
}e[maxn];
int cnt_e;

int n, m;
long long a[maxn];

int f[maxn];

bool cmp(const Edge& a, const Edge& b) {
  return a.w < b.w;
}

int Find(int x) {
  if(x != f[x]) f[x] = Find(f[x]);
  return f[x];
}

int main() {
  scanf("%d%d", &n, &m);
  for(int i = 1; i <= n; i ++) {
    scanf("%lld", &a[i]);
    f[i] = i;
  }

  int index = 1;
  for(int i = 2; i <= n; i ++) {
    if(a[i] < a[index]) {
      index = i;
    }
  }

  for(int i = 1; i <= n; i ++) {
    if(i == index) continue;
    e[cnt_e].x = i;
    e[cnt_e].y = index;
    e[cnt_e].w = a[i] + a[index];
    cnt_e ++;
  }

  while(m--) {
    scanf("%d%d%lld", &e[cnt_e].x, &e[cnt_e].y, &e[cnt_e].w);
    cnt_e ++;
  }

  sort(e, e + cnt_e, cmp);
  long long ans = 0;
  for(int i = 0; i < cnt_e; i ++) {
    int fx = Find(e[i].x);
    int fy = Find(e[i].y);
    if(fx == fy) continue;

    ans = ans + e[i].w;
    f[fx] = fy;
  }

  printf("%lld\n", ans);

  return 0;
}
相關文章
相關標籤/搜索