日常训练2025-1-19

日常训练2025-1-19

C. Light Switches

rating:1500

https://codeforces.com/problemset/problem/1993/C

思路(Trick)

首先明确一点,当所有的芯片安装完成后,才有可能所有的灯会亮

可以求出芯片安装时刻的最大值max_val

然后就是芯片装好一瞬间就会亮,周期是2k,

现在需要考虑的就是每一个芯片安装时刻到所有装完(max_val)这一段时间是否满足在k内即可

代码

#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;
	std::cin >> n >> k;

	int maxx = 0;
	std::vector<int> a(n+1);
	for (int i = 1; i <= n; i++) {
		std::cin >> a[i];
		maxx = std::max(a[i], maxx);
	}	

	// l:最后一个灯安装时,没亮的灯中最晚亮的灯需要走l步。
	// r:最后一个灯安装时,亮的灯中最早灭的灯在r步后才会灭
	int l = 0, r = k;
	for (int i = 1; i <= n; i++){
		int x = (maxx - a[i]) % (2 * k);
		if (x == k){
			l = r + 1;
			break;
		}
		if (x < k){
			r = std::min(r, k - x - 1);
		}
		if (x > k){
			l = std::max(l, 2*k - x);
		}
	}
	if (l > r){
		std::cout << "-1\n";
	}else{
		std::cout << maxx + l << '\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;
}

C. Mad MAD Sum

rating:1500

https://codeforces.com/problemset/problem/1990/C

思路(Trick)

b数组是前i个数中,中出现次数大于等于2的最大的数。由此我们可以得出经过一次操作以后,得到的新数组一定是单调不减。此时还有可能出现数量为一的数。,所以我们要再进行一次操作,那样这些只出现一次都数都会被左边替代,这样的话得到的数的出现次数都是大于2。往后就是非零部分向右移动。

代码

#include<bits/stdc++.h>
using namespace std ;
#define int long long
int t;
int n;
int sum;
int maxn;
map<int,int> mp ;
signed main()
{
    cin>>t ;
    while(t--)
    {
    	mp.clear();
        cin >> n ;
        vector<int> a(n+5);
        sum = 0 ;
        int maxn = 0 ;
        for(int i = 0 ; i < n ; i ++ )
        {
            cin >> a[i] ;
            sum += a[i] ;
            mp[a[i]] ++ ;
            if(mp[a[i]] >= 2 && a[i] > maxn)
            {
                maxn = a[i] ;
            }
            a[i] = maxn ;
        }
        mp.clear() ;
        maxn = 0 ;
        for(int i = 0 ; i < n ; i ++ )
        {
            sum += a[i] ;
            mp[a[i]] ++ ;
            if(mp[a[i]] >= 2 && a[i] > maxn)
            {
                maxn = a[i] ;
            }
            a[i] = maxn ;
        }
        for(int i = 0 ; i < n ; i ++ )
        {
            sum += (n - i) * a[i] ;
        }
        cout << sum << endl ;
    }
    return 0 ;
}

F. Final Boss

rating:1500

https://codeforces.com/problemset/problem/1985/F

思路(二分)

要理解清楚题意,放了 i 号技能,是 i 号技能会陷入冷却,但是我们还可以用其他技能,角色是不会陷入冷却的。所以如果知道回合数 x 的情况下,我们可以很快的算出我们能用多少个 i 号技能,对于其他任何技能也一样可以很快算出来。所以标准的二分题。答案满足单调性,猜测答案的情况下很容易判断是否可行

评述

原本在想这道题会不会是DP,结果DP有点难,贪心也不现实。看了一眼Jiangly的代码,二分秒了。

代码

#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 h, n;
	std::cin >> h >> n;

	std::vector<int> v(n+1), w(n+1);
	for (int i = 1; i <= n; i++){
		std::cin >> v[i];
	}
	for (int i = 1; i <= n; i++){
		std::cin >> w[i];
	}

	i64 l = 1, r = 1e11;
	while (l < r){
		i64 x = (l + r) >> 1;
		i64 dmg = 0;
		for (int i = 1; i <= n; i++){
			dmg += (x + w[i] - 1) / w[i] * v[i];
			if (dmg >= h) break;
		}

		if (dmg >= h){
			r = x;
		}else{
			l = x + 1;
		}
	} 

	std::cout << l << '\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;
}

D. Ingenuity-2

rating:1400

https://codeforces.com/problemset/problem/1974/D

思路(思维)

由于初始两人在同一点,那么我们想要保证两人最终在同一点,首先,相反方向可以让一个人走,就可以相互抵消,对于没有抵消的部分,如果是偶数次,那么就可以两人一起走,反之,则无解。所以直接判断相反方向的奇偶性是否相同即可。

注意一些特判,n=2时,必须两条指令相同,因为每人至少走一步。对于 n=4,并且每个方向走出现一次的情况。我们也需要分别让每个人走一对相反的方向即可。

代码

#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;
   string s;
   cin >> s;
   map<char, int> mp;
   for (auto c : s) mp[c]++;
   if (n == 2 && s[0] != s[1]) return cout << "NO\n", void();
   if (n == 4 && mp['N'] && mp['S'] && mp['E'] && mp['W']) {
      for (auto c : s) {
         if (c == 'N' || c == 'S') cout << "R";
         else cout << "H";
      }
      cout << endl;
      return;
   }
   if ((mp['N'] & 1) != (mp['S'] & 1) || (mp['E'] & 1) != (mp['W'] & 1)) return cout << "NO\n", void();

   map<char, int> mp2;
   for (auto c : s) {
      mp2[c]++;
      cout << (mp2[c] & 1 ? "R" : "H");
   }
   cout << 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;
}

C. Beautiful Triple Pairs

rating:1400

https://codeforces.com/problemset/problem/1974/C

思路

首先可见三元组的个数并不多, 所以我们可以考虑记录下第一个,第二个相等的个数s1,第一个,第三个相等的个数s2, 第二个,第三个相等的个数s3, 然后在记录全部相等的个数s,那么[x, y, z]能够给答案做出的贡献为s1 + s2 + s3 - 3 * s, 由于种情况会统计两次,所以最后除以2

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
 
using namespace std;
 
typedef long long ll;
typedef pair<int, int> pii;
typedef tuple<int, int, int> t3;
 
const int N = 2e5 + 10;
 
ll a[N];
 
void solve()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++ )
        cin >> a[i];
    
    map<t3, ll> mp;// 存三元组[x, y, z]的个数
    map<t3, ll> mp2;//存[x, y, 0], [x, 0, z], [0,, y, z]的个数
    for (ll i = 2; i < n; i ++ )
    {
        mp[{a[i - 2], a[i - 1], a[i]}] ++ ;
        mp2[{a[i - 2], a[i - 1], 0}] ++ ;
        mp2[{a[i - 2], 0, a[i]}] ++ ;
        mp2[{0, a[i - 1], a[i]}] ++ ;
    }
 
    ll res = 0;
    for (int i = 2; i < n; i ++ )
    {
        res += mp2[{a[i - 2], a[i - 1], 0}];
        res += mp2[{a[i - 2], 0, a[i]}];
        res += mp2[{0, a[i - 1], a[i]}];
        res -= 3 * mp[{a[i - 2], a[i - 1], a[i]}];
        // mp[{a[i - 2], a[i - 1], a[i]}] -- ;
        // mp2[{a[i - 2], a[i - 1], 0}] -- ;
        // mp2[{a[i - 2], 0, a[i]}] -- ;
        // mp2[{0, a[i - 1], a[i]}] -- ;
    }
    cout << res / 2 << endl;
}
 
int main()
{
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}
posted @ 2025-01-19 09:08  califeee  阅读(22)  评论(0)    收藏  举报