日常训练2025-1-22

日常训练2025-1-22

F Tokitsukaze and Eliminate (hard)

https://ac.nowcoder.com/acm/contest/67742/F

思路(小巧思)

标准的Trick题,构造一个样例来模拟一下会发现,在删的那个数的位置之后的每一种数都至少出现了一次,他是最后出现的。模拟这个过程就行。

代码

#include <bits/stdc++.h>

typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;

using namespace std;

void solve(){
        int n;
        cin>>n;
        vector<int>a(n+1);
        map<int,int>mp1,mp2;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            mp1[a[i]]++;
        }
        int pos=mp1.size();
                int ans=0;
        for(int i=n;i>=1;i--){
            if(mp1.size()==1){
                ans+=i;
                break;
            }
            mp2[a[i]]++;
            mp1[a[i]]--;
            if(mp1[a[i]]==0) mp1.erase(a[i]);
            if(mp2.size()==pos){
                ans++;
                mp2.clear();
                pos=mp1.size();
            }
        }
        cout<<ans<<endl;
}

signed main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
	int t = 1, i;
	std::cin >> t;
	for (i = 0; i < t; i++){
		solve();
	}
	return 0;
}

Tokitsukaze and Slash Draw

https://ac.nowcoder.com/acm/contest/67742/D

思路(最短路)

将题目的模型建出来发现其实就是一个图。我们跑一个 Dij 算法即可。

代码

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int tc;
  cin >> tc;

  while (tc--) {
    int n, m, k;
    cin >> n >> m >> k;

    vector a(m, 0), b(n, 0);
    for (int i = 0; i < m; i++) {
      cin >> a[i] >> b[i];
    }

    std::vector<int> vis(n);
    vector dp(n, -1ll);
    dp[k % n] = 0;
    priority_queue<int, std::vector<int>, std::greater<>> q;
    q.push(k % n);
    while (q.size()) {
      int u = q.top();
      q.pop();
      if (vis[u]) continue;
      vis[u] == 1;
      for (int i = 0; i < m; i++) {
        int v = (u + a[i]) % n;
        if (dp[v] == -1 || dp[v] > dp[u] + b[i]){
          dp[v] = dp[u] + b[i];
          if (vis[v] == 0) q.push(v);
        }
      }
    }

    // for (int i = 0; i < n; i++) {
    //   cerr << dp[i] << ' ';
    // }

    cout << dp[0] << '\n';
  }

  return 0;
}

E. Find the Car

rating:1500

https://codeforces.com/problemset/problem/1971/E

思路(二分)

直接二分找第一个比他大的标志为在哪,然后使用初中计算公式算一下就行了。

代码

#include <bits/stdc++.h>

typedef std::pair<long long, long long> pll;
typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;

void solve(){
	int n, k, q;
	std::cin >> n >> k >> q;

	std::vector<int> a(k+1), b(k+1);
	for (int i = 1; i <= k; i++){
		std::cin >> a[i];
	}

	for (int i = 1; i <= k; i++){
		std::cin >> b[i];
	}

	for (int i = 0; i < q; i++){
		int x; std::cin >> x;

		i64 ans = 0;
		int idx = std::lower_bound(a.begin(), a.end(), x) - a.begin();
		if (idx == 0){
			;
		}else{
			ans = b[idx - 1] + 1LL * (x - a[idx-1]) * (b[idx] - b[idx-1]) / (a[idx] - a[idx-1]);
		}

		std::cout << ans << ' ';
	}
	std::cout << '\n';
}

signed main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
	int t = 1, i;
	std::cin >> t;
	for (i = 0; i < t; i++){
		solve();
	}
	return 0;
}

A. Permutation Counting

rating:1400

https://codeforces.com/problemset/problem/1967/A

思路1(类模拟)

使用模拟的思路计算用k补齐之后,最小值最大能得多少,然后统计答案即可。注意,多出来的 k 和多出来的数都可以额外地贡献答案。

代码1

#include <bits/stdc++.h>

using i64 = long long;

void solve() {
    int n;
    i64 k;
    std::cin >> n >> k;
    
    std::vector<i64> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    std::sort(a.begin(), a.end());
    
    i64 maxx = a[0];
    for (int i = 1; i < n; i++){
    	if (i*(a[i]-a[i-1]) <= k){
    		k -= i * (a[i] - a[i-1]);
    		maxx = a[i];
    	}else{
    		maxx += k / i;
    		k %= i;
            break;
    	}
    }

    i64 ans =  maxx * n + k - n + 1;
    for (int i = 0; i < n; i++){
    	if (a[i] > maxx){
    		ans++;
    	}
    }

    std::cout << std::max(ans, 0LL) << '\n';
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int t;
    std::cin >> t;
    
    while (t--) {
        solve();
    }
    
    return 0;
}

思路2(二分)

这里用二分找最小值最大能得多少,其他的基本一至。

代码2

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

const int maxn = 2e6 + 5;

typedef long long ll;
typedef pair<ll,ll> pii;
ll n, k;
ll a[maxn];

bool check(ll x) {
    ll need = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] < x) need += x - a[i];
    }
    return need <= k;
}

void solve() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i];
    ll left = 1, right = 2e12;
    ll mn;
    // 求能达到的最小值
    while (left + 1 < right) {
        ll mid = (left + right) / 2;
        if (check(mid)) left = mid;
        else right = mid;
    }
    if (check(right)) mn = right;
    else mn = left;

    for (int i = 1; i <= n; i++) {
        if (a[i] < mn) {
            ll t = mn - a[i];
            a[i] += t, k -= t;
        }
    }
    ll num = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] == mn && k ) a[i]++, k--;
        if (a[i] > mn) num++;
    }
    ll ans = n * (mn - 1) + 1 + num;
    cout << ans << endl;
}
//? ? ? 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    int T;
    cin >> T;
    while (T--) solve();
}

A. Everything Nim

rating:1400

https://codeforces.com/problemset/problem/1965/A

思路(博弈)

思考一下会发现,当序列中存在1是,只能取1,没有其他办法,如果没有1了,那么此时先手一定必胜。

代码

#include <bits/stdc++.h>

using i64 = long long;

using namespace std;

void solve() {
    int n; cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
    n = a.size();
    int round = 0;
    for (int i = n - 1; i > 0; i--) a[i] -= a[i - 1];

    reverse(a.begin(), a.end());
    while (a.size() && a.back() == 1) {
        a.pop_back(), round ^= 1;
    }
    if (a.size() == 0) round ^= 1;
    cout << (round ? "Bob" : "Alice") << '\n';
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int t;
    std::cin >> t;
    
    while (t--) {
        solve();
    }
    
    return 0;
}
posted @ 2025-01-22 13:25  califeee  阅读(18)  评论(0)    收藏  举报