SMU2025寒假训练周报2

这周状态其实不太好,很多时候心急总是卡简单题,中档题也有些难a,希望尽快调整

一.个人训练赛2

1. Linova and Kingdom

题目链接:Problem - C - Codeforces

每加一个点总体贡献就可能发生变化,那我们就处理每个点的贡献,将他的深度减去他孩子的总个数就是贡献,最后排序取最大的k个即可

查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
vector<int>v[1000000];
vector<int>z;
int sign[1000000];
int dfs(int x,int y,int deep)
{
    sign[x]=1;
    int ans=1;
    for(int i=0;i<v[x].size();i++)
    {
       if(v[x][i]!=y){
           ans+=dfs(v[x][i],x,deep+1);
       }
    }
    z.push_back(deep+1-ans);
    //if(!bj)z.push_back(deep);
    return ans;
}
signed main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1,0,0);
    sort(z.begin(),z.end(),greater());
    int sum=0;
    int ans=0;
    for(int i=0;i<z.size();i++)
    {
        if(ans==k)break;
        sum+=z[i];
        ans++;
    }
    cout<<sum;
    return 0;
}

2. Xenia and Colorful Gems

题目链接:Problem - D - Codeforces

一共就只有六种大小关系,将三种石头排序,从每种情况最小的数组开始遍历查找在另外俩个数组有无跟她相差很小的石头,如果最终结果缩小就更新

查看代码
 void solve(int *x, int *y, int *z, int nx, int ny, int nz)
{
	int p1 = 0, p2 = 0;
	for(int i = 1; i <= nx; i++)
	{
		while(p1 <= ny && y[p1] <= x[i]) p1++;  //找最接近的较小值
		while(p2 <= nz && z[p2] < x[i]) p2++;  //找最接近的较大值
		if(p1 - 1 != 0 && p2 != nz + 1)  //较小值和较大值都能找到
			ans = min(ans, calc(x[i], y[p1 - 1], z[p2]));
	}
	return;
}

二.牛客训练营4

1.Tokitsukaze and Balance String (hard)

题目链接:C-Tokitsukaze and Balance String (hard)_2025牛客寒假算法基础集训营4

easy版直接二进制枚举,这个n太大了,这题是有规律的,还是要多看多总结

查看代码
 for (int i = 1; i <= n-2; i++) {
        if(s[i] == '?')k++;
    }
    int k = qpow(2,k);
    if(s[0] == '0' && s[n-1] == '0')
    {
        cout << k*(n-2)%mod << endl;
    }
    else if(s[0] == '1' && s[n-1] == '1')
    {
        cout << k*(n-2)%mod << endl;
    }
    else if(s[0] == '0' && s[n-1] == '1') 
    {
        cout << k*2%mod << endl;
    }
    else if(s[0] == '1' && s[n-1] == '0')
    {
        cout << k*2%mod << endl;
    }
    else if(s[0] == '?' && s[n-1] != '?') 
    {
        cout << k*n%mod << endl;
    }
    else if(s[0] != '?' && s[n-1] == '?') 
    {
        cout << k*n%mod << endl;
    }
    else if(s[0] == '?' && s[n-1] == '?') 
    {
        cout << k*n*2%mod << endl;
    }

2.Tokitsukaze and Concatenate‌ Palindrome

原题链接:D-Tokitsukaze and Concatenate‌ Palindrome_2025牛客寒假算法基础集训营4

用长串的字母去补短串,长串没有的就sum++,有的就该字母个数减一,并计算最后长串字母数量为奇数的个数ans,ans和sum就是需要进行操作的字母,如果sum更多那就让sum去和ans对应,因为sum所在的串短,总操作数为sum;反之就取ans+sum的一半 

查看代码
 #include<bits/stdc++.h>

using namespace std;

int main(){
    int T;
    cin >> T;
    while(T--){
        int n, m;
        cin >> n >> m;
        string s, t;
        cin >> s >> t;
        if(n < m){
            swap(n, m);
            swap(s, t);
        }
        map<int, int> mp;
        for(auto &i : s){
            mp[i]++;
        }
        int sum = 0;
        for(auto &i : t){
            if(mp[i]) mp[i]--;
            else sum++;
        }
        int ans = 0;
        for(auto &[x, y] : mp){
            if(y & 1) ans++;
        }
        if(sum >= ans) ans = sum;
        else{
            ans=(ans+sum)/2;
        }
        cout << ans << endl;
    }
}

三.牛客训练营3

1.小L的位运算

原题链接:C-小L的位运算_2025牛客寒假算法基础集训营5

统计每种情况,如果都不超过半数那么都可以进行交换,如果有超过的就让超过的那部分自己进行反置操作即可,同时也要注意交换和反置的代价大小。

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
    int n,x,y;
    cin>>n>>x>>y;
    string a,b,c;
    cin>>a>>b>>c;
    y=min(y,2*x);
    int a00=0,a01=0,a10=0,a11=0,ans=0;
    for (int i = 0; i < n; ++i){
        if (a[i] == '0' && b[i] == '0' && c[i] == '1') a00++,ans++;
        if (a[i] == '0' && b[i] == '1' && c[i] == '0') a01++,ans++;
        if (a[i] == '1' && b[i] == '0' && c[i] == '0') a10++,ans++;
        if (a[i] == '1' && b[i] == '1' && c[i] == '1') a11++,ans++;
    }int sum = 0;
    int ma=max({(int)0,a00,a01,a10,a11});
    int ban=ans/2;
    if(ma*2>ans)ban=ans-ma;
    cout<<ban*y+(ans-ban*2)*x;
    return 0;
}

2.小L的井字棋

原题链接:E-小L的井字棋_2025牛客寒假算法基础集训营5

首先如果棋盘上没有棋子,那么我们下中间,然后再使用特权随便下两个可以连起来的地方,即可胜利。
如果棋盘上已经各有一颗棋子,那么这颗棋子一定至少有一个方向没有对方的棋子,我可以直接使用特权胜利。
如果棋盘上已经各有四颗棋子,直接填入后判断即可。
如果棋盘上已经各有三颗棋子,那么一定是使用特权更优,三种方式枚举一下,结果或起来即可。
如果棋盘上已经各有两颗棋子,手算枚举一下各个情况,发现无论怎么下都是先手必胜的,直接Yes即可。

3.小L的构造

原题链接:L-小L的构造_2025牛客寒假算法基础集训营5

根据mod6余数分类判断,且有固定组合

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
    int t;
    cin>>t;
    while(t--) {
        int n;
        cin >> n;
        if (n <= 3)cout<<0<<endl;
        else
        {
            cout<<n/3<<endl;
            if(n<6)cout<<"1 2 4"<<endl;
            else if(n%6<=2)
            {
               for(int i=1;i<=n;i+=6)
               {
                  if(i+3<=n) cout<<i<<" "<<i+1<<" "<<i+3<<endl;
                   if(i+5<=n)cout<<i+2<<" "<<i+4<<" "<<i+5<<endl;
               }
            }
            else
            {
                cout<<"1 2 4"<<endl;
                cout<<"3 9 5"<<endl;
                cout<<"6 8 7"<<endl;
                for(int i=10;i<=n;i+=6)
                {
                    if(i+4<=n)cout<<i<<" "<<i+1<<" "<<i+4<<endl;
                    if(i+5<=n)cout<<i+2<<" "<<i+3<<" "<<i+5<<endl;
                }
            }
        }
    }
    return 0;
}
posted @ 2025-02-09 15:05  伊芙加登  阅读(22)  评论(0)    收藏  举报