2023牛客寒假算法基础集训营第五场题解(A-M 转本人知乎)

比赛链接:[2023牛客寒假算法基础集训营5]

比赛情况: 8/138/138/13

本场个人觉得难度排行: $$A≤C≤L≤H≤K≤D≤M≤G≤F≤E≤B≤I≤JA\le C\le L\le H\le K\le D\le M\le G\le F\le E\le B\le I\le JA\le C\le L\le H\le K\le D\le M\le G\le F\le E\le B\le I\le J$$

只A了8题,最后两个小时有事情要去拜年,去亲戚家了~~只好先润了!!!5555555

wtcl!!!!wwwwwwwwwww

赛时情况:

自认为 签到 A B K H 中等题:L C D I 难题 E F G J

A题 小沙の好客

二分+前缀和

void solve() {
  int n, q;
  cin >> n >> q;
  vector<int>a(n + 10), sum(n + 10);
  rep(i, 1, n)cin >> a[i];
  sort(a.begin() + 1, a.begin() + 1 + n);
  rep(i, 1, n)sum[i] = sum[i - 1] + a[i];
  while (q--){
    int k, x; cin >> k >> x;
    int t = upper_bound(a.begin() + 1, a.begin() + 1 + n, x) - a.begin();
    if (t == n + 1 || a[t] > x)t--;
    cout << sum[t] - sum[max(t - k, 0LL)] << endl;
  }
}

B题 小沙の博弈

void solve() {
  int n; cin >> n;
  if (n & 01)
    cout << "Yaya-win!" << endl;
  else cout << "win-win!" << endl;
}

K题 小沙の抱团 easy

void solve() {
  int n; cin >> n;
  int res = 0;
  while (n > 2) {
    res++;
    if (n & 01) {
      n++;
      n = n / 2;
    }
    else {
      n++; n++;
      n >>= 1;
    }
  }
  cout << res << endl;
}

H题 小沙の店铺

void solve() {
  int x, y, k, n, t;
  cin >> x >> y >> k >> n >> t;
  int ans = 0, cn = 0;
  per(i, n, 1) {
    ans += x * i;
    cn += i;
    if (cn >= k)
      x += ((int)cn / k) * y, cn %= k;
    if (ans >= t) {
      out(n - i + 1);
      return;
    }
  }
  out(-1);
}

L题 小沙の抱团 hard

DP

dp[N]含义为 当最小为i时的最小代价

背包思想

void solve() {
  int n, M; cin >> n >> M;
  vector<int>w(M + 10), x(M + 10), dp(100000 + 10, inf);
  rep(i, 1, M)cin >> w[i] >> x[i];
  if (n == 1 || n == 2) {
    out(0);
    return;
  }
  dp[n] = 0;
  per(j, n, 1) {
    rep(i, 1, M) {
      int W = w[i], X = x[i];
      if (X > j)continue;
      dp[j - j % X] = min(dp[j - j % X], dp[j] + W);
    }
  }
  int ans = 0;
  rep(i, 1, n) {
    if (dp[i] != dp[100001]) {
      out(dp[i]);
      return;
    }
  }
}

C题 小沙の不懂

用用sjjj的题解
由于当字符串长度不等时,一定存在长的大于短的,那么我们仅需要去寻找当长字符串尽可能小时, 是否小于短字符串即可判断,这里可以根据自己的思路自由发挥。

int main() {
  string s, t;
  cin >> s >> t;
  if (s.size() != t.size()) {
    bool flag = 0;
    if (s.size() < t.size())flag = 1, swap(s, t);
    set<char>ft;
    for (ri i = 0; i < s.size() - t.size(); ++i)ft.insert(s[i]);
    if (ft.size() > 1)return putchar(flag ? '<' : '>'), 0;
    string _s = s.substr(s.size() - t.size(), t.size());
    for (ri i = 0; i < t.size(); ++i)
      if (_s[i] != t[i]) {
        if (t[i] == s[0])return putchar(flag ? '<' : '>'), 0;
        break;
      }
    putchar('!');
  }
  else putchar(s == t ? '=' : '!');
  return 0;
}

D题 小沙の赌气

赛中我直接用set模拟了,但是赛后我想用动态开点的权值线段树写写,之后补吧

void solve()
{
  int n;
  cin >> n;
  vector<node> a(n + 10), b(n + 10);
  rep(i, 1, n)cin >> a[i].l >> a[i].r, ++a[i].r;
  rep(i, 1, n)cin >> b[i].l >> b[i].r, ++b[i].r;
  set <node> pa, pb;
  int va = 1, vb = 1;
  auto cacl = [](set<node>& p, node x, int& h) {
    p.insert(x);
    while (!p.empty() && h >= p.begin()->l) {
      h = max(h, p.begin()->r);
      p.erase(p.begin());
    }
  };
  rep(i, 1, n) {
    cacl(pb, b[i], vb);
    cacl(pa, a[i], va);
    if (va < vb)
      out("ya_win!");
    else if (va == vb)
      out("win_win!");
    else
      out("sa_win!");
    out(abs(va - vb));
  }
}

I题 小沙の金银阁

这思维题 要想不亏 那n-1轮肯定是前缀和<=第n轮,尽可能等于

void solve() {
  int n, m;
  cin >> n >> m;
  vector<int>a(n + 10);
  per(i, n, 1)
  {
    if (i != 1)
      a[i] = (m + 1) >> 1;
    else
      a[i] = m;
    m -= a[i];
  }
  if (!a[1]) {
    out(-1); return;
  }
  rep(i, 1, n)
    cout << a[i] << " \n"[i == n];
}

F题 小沙の串串

写这题前我们先AC下这题 力扣 402. 移掉 K 位数字这题

class Solution {
public:
#define rep(i,a,n) for (int i=a;i<=n;i++)   
  string removeKdigits(string s = "1432219", int k = 3) {
    string str;
    vector<int>st;
    int len = s.size();
    rep(i, 0, len - 1) {
      while (!st.empty() && k > 0 && st.back() > s[i] - '0'){
        st.pop_back();
        k--;
      }
      st.push_back(s[i] - '0');
    }
    while (k--)st.pop_back();
    for (auto& i : st)str += i + '0';
    int cn = 0;
    while (str[cn] == '0')cn++;
    str = str.substr(cn, (int)str.size());
    return str.empty() ? "0" : str;
  }
};

这题不同点在于,我们可以对几个进行sort

void solve() {
  int n, k;
  string s, ans, res;
  cin >> n >> k >> s;
  rep(i, 0, n - 1) {
    while (k && !ans.empty() && ans.back() < s[i])
      k--, res.push_back(ans.back()), ans.pop_back();
    ans.push_back(s[i]);
  }
  while(k&&!ans.empty())
    k--, res.push_back(ans.back()), ans.pop_back();
  sort(res.rbegin(), res.rend());
  cout << ans + res << endl;
}

G题 小沙の编码

网络流

我们已经知道a[1],a[3],a[5]......的数值,需要找出剩下n/2个元素

我们需要合法的边,那么我们只需要进行匹配,a[2]=now,now既要满足与a[1]二进制差一,也要满足与a[3]二进制差一,我们直接枚举二进制位异或就可以了,预处理p2数组

DINIC<N> G;

void solve() {
  vector<int>p2(N);
  rep(i, 0, 17)p2[1LL << i] = i;
  p2[1] = 1;
  int n; cin >> n;
  vector<int>a(n + 10, 0);
  vector<bool>vis(N, false);
  for (int i = 1; i <= n; i += 2)cin >> a[i], vis[a[i]] = true;
  //1 2 st
  G.S = 1, G.T = 2;
  memset(G.head, -1, sizeof G.head);

  int m = p2[n];
  for (int i = 2; i <= n - 2; i += 2)
  {
    G.add(1, 2 + i, 1), G.add(2 + i, 1, 0);
    rep(j, 0, m - 1) {
      int now = a[i - 1] ^ (1LL << j);
      if (p2[now ^ a[i + 1]] && !vis[now])
      {
        G.add(2 + i, 3 + n + now, 1);
        G.add(3 + n + now, 2 + i, 0);
      }
    }
  }
  G.add(1, 2 + n, 1); G.add(2 + n, 1, 0);
  //特判最后一个点
  rep(j, 0, m - 1) {
    int now = a[n - 1] ^ (1LL << j);
    if (!vis[now])
    {
      G.add(2 + n, 3 + n + now, 1);
      G.add(3 + n + now, 2 + n, 0);
    }
  }
  //二分图左边连右边建立好边
  rep(i, 0, n - 1)
    G.add(3 + n + i, 2, 1), G.add(2, 3 + n + i, 0);
  G.Dinic();
  for (int i = 2; i <= n; i += 2) {
    for (int j = G.head[i + 2]; ~j; j = G.edge[j].next)
    {
      int flow = G.edge[j].cap;
      if (!flow && G.edge[j].to >= n + 3)
        a[i] = G.edge[j].to - n - 3;
    }
  }
  rep(i, 1, n)cout << a[i] << " \n"[i == n];
}

E题 小沙の印章

不懂 看题解还是晕嘘嘘

构造

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using LL = long long;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
void solve(){
	int n;
	cin >> n;
	vector<int> a(n);
	iota(a.begin(), a.end(), 1);
	vector<vector<PII>> ans;
	while(!is_sorted(a.begin(), a.end(), greater<int>())){
		vector<PII> seg;
		for(int i = 1; i < n; i ++ ){
			if(a[i] > a[i - 1]){
				seg.push_back({a[i], a[i - 1]});
				swap(a[i], a[i - 1]);
				i ++ ;
			}
		}
		ans.push_back(seg);
	}
	cout << ans.size() << endl;
	for(auto v: ans){
		cout << v.size() << endl;
		for(auto [x, y] : v){
			cout << x << " " << y << endl;
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	solve();
	return 0;
}

J题 小沙の最短路

构造 有缘再补吧

本人这篇文章发布于 知乎
发布于 2023-02-06 22:53・IP 属地安徽

posted @ 2023-09-28 11:19  Nondifferent  阅读(9)  评论(0编辑  收藏  举报