Codeforces Round #790(Div.4) A----G题解

题目大意:输入一个字符串,该字符串包含6个数字,如果前三位数字等于后三位数字之和,输出”YES“,否则输出”NO“;

思路: 签到题,直接把前三位和后三位的和加起来,比较是否相同即可。

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int t;
    cin>>t;
    for(int i = 1;i<=t;i++)
    {
        string a;
        cin>>a;
        int sum1 = 0,sum2 = 0;
        for(int j = 0;j <= 2;j ++) sum1 += a[j]-'a';
        for(int j = 3;j <= 5;j ++) sum2 += a[j]-'a';

        if(sum1 == sum2) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

 

题目大意:一共有n个箱子,在每个箱子里有ai个糖果,现在需要把箱子分给朋友,但要求,每个朋友获得的糖果数相同,每个箱子给不同的朋友,问,他需要吃掉多少个糖果,才能分配均匀。

思路:可以转化为把不同箱子中包含糖果最少的那个数分给朋友们,既求糖果数总和和箱子数*最小糖果数的差值.

#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 60;
 
int a[N];
 
int main()
{
    int t;
    cin>>t;
    for(int k = 1;k <= t;k++)
    {
        int sum = 0;
        int mi = 0x3f3f3f3f;
        int res = 0;
        int n;
        cin>>n;
        for(int i = 1;i <= n;i ++)
        {
            int x;
            cin>>x;
            sum += x;
            if(mi > x) mi = x;
        }
        res = sum - mi * n;
        cout<<res<<endl;
    }
    return 0;
}

 

 

题目大意:   输入n个长度为m的单词, 在这n个单词中,两两间每一位上的字母距离的和的最小值。

思路:字母间的距离即为字母间ASCII码的差值,注意数据范围,n在50以内,m在8以内,直接暴力枚举字母间距离之和然后求最小值即可。

#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 60;
 
string str[60];
 
int main()
{
    int t;
    cin>>t;
    for(int k = 1;k <= t;k++)
    {
        int idx;
        int sum = 0x3f3f3f3f;
        int n,m;
        cin>>n>>m;
        for(int i = 1;i <= n;i ++) cin>>str[i];
 
        for(int i = 1;i < n;i++)
        {
            for (int j = i + 1; j <= n; j++)
            {
                idx = 0;
                for(int p = 0;p < m;p ++)
                {
                    int a = str[i][p] - 'a';
                   // cout<<a<<endl;
                    int b = str[j][p] - 'a';
                    //cout<<b<<endl;
                    idx += abs(a - b);
                   // cout<<idx<<endl;
                }
                sum = min(sum,idx);
            }
           // sum = min(sum,idx);
        }
 
        cout<<sum<<endl;
    }
    return 0;
}

 

题目大意:给一个n行m列的棋盘,每个格子上都有一个非负整数,把一个主教放在棋盘的一个位置,求被主教攻击的 所有格子上的数字的和的最大值(主教能攻击正负对角线上的所有棋子)

思路:数据范围比较小,直接枚举即可。枚举每一个位置,在该位置枚举四个方向所有能够到达的格子上的数之和。最后求最大值即可。

#include <bits/stdc++.h>
 
using namespace std;
 
int main()
{
	int t, n, m;
 
	cin >> t;
	while(t--)
	{
		cin >> n >> m;
		int ara[n+8][m+8];
 
		for(int i = 0; i < n; i++)
		{
			for(int j = 0; j < m; j++)
			{
				cin >> ara[i][j];
			}
		}
		int sum, mx = -0x3f3f3f3f;
		for(int i = 0; i < n; i++)
		{
			for(int j = 0; j < m; j++)
			{
				sum = 0;
				for(int a = i, b = j; a < n && b < m; a++, b++)
				{
					sum += ara[a][b];
				}
				for(int a = i-1, b = j-1; a >= 0 && b >= 0; a--, b--)
				{
					sum += ara[a][b];
				}
				for(int a = i+1, b = j-1; a < n && b >= 0; a++, b--)
				{
					sum += ara[a][b];
				}
				for(int a = i-1, b = j+1; a >= 0 && b < m; a--, b++)
				{
					sum += ara[a][b];
				}
 
				if(mx < sum)
				{
					mx = sum;
				}
			}
		}
 
		cout << mx << endl;
	}
	return 0;
}

 

 

题目大意: 有n个糖果,每个糖果的含糖量是ai,一共有q次询问,每次询问给一个x,问最少吃多少个糖,总的含糖量能大于等于x。

思路:维护一个前缀和来存糖果的总的含糖量,然后在每次询问中,通过二分查找找到第一个大于等于x的下标,然后,如果下标大于等于n,则说明全部加起来也不够x,输出-1,否则输出pos(也就是二分查找到的下标)的上一位,既pos - 1; (注意数据范围,如果裸暴力找第一个大于等于x的的下标的话,会TLE的。实测:在第6个样例就爆了)

注:STL中自带二分查找函数:  二分查找icon-default.png?t=M4ADhttps://blog.csdn.net/qq_41785863/article/details/80905592?ops_request_misc=&request_id=&biz_id=102&utm_term=%E4%BA%8C%E5%88%86stl&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-80905592.142^v9^control,157^v4^control&spm=1018.2226.3001.4187

(暴力大法,反面教材,这里就不上代码了)

(二分查找)

#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 1.5e5+10;
 
int a[N],sum[N];
 
int ans;
 
bool cmp(int b,int c)
{
    return b > c;
}
 
int main()
{
    int t;
    cin>>t;
    for(int te = 1;te <= t;te ++)
    {
        memset(a,0,sizeof a);
        memset(sum,0,sizeof sum);
        int n,q;
        cin>>n>>q;
        for(int i = 1;i <= n;i ++) cin>>a[i];
 
        sort(a+1,a+1+n, cmp);
 
        sum[0] = 0;
        for(int i = 1;i <= n;i ++) sum[i] = sum[i-1] + a[i]; //前缀和
 
        for(int qe = 1;qe <= q;qe ++)
        {
            int x;
            cin>>x;
            int pos = lower_bound(sum + 1,sum + n + 1,x) - sum - 1;
            if(pos >= n) cout<<"-1"<<endl;
            else cout<<pos+1<<endl;
        }
    }
    return 0;
}

 

 

 题目大意: 首先,给一个长度为n的数组,和出现次数k,需要找到 一对l,r,保证对于每一个x,l<=x<=r,x在数组中出现次数大于等于k,并且要求r-l的值最小。

思路:用map存每个数出现的次数,然后去重存入vector中,对vector数组进行排序,然后双指针直接枚举就好。

注意:在用map存数字出现次数的时候,记录一下数字出现的最大次数,如果小于k,则无解,输出-1即可。

#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 1e6 + 10;
 
int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, k, x;
        cin >> n >> k;
        map<int, int> m, v;
        vector<int> q;
        int mx = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &x);
            m[x]++;
            if (m[x] >= k && !v[x]) {
                v[x] = 1;
                q.push_back(x);
            }
            mx = max(mx, m[x]);
        }
        if (mx < k)puts("-1");
        else {
            sort(q.begin(), q.end());
            int l = q[0], r = q[0];
            mx = 0;
            int ans = 0, last = q[0];
            for (int i = 1; i < q.size(); i++) {
                if (q[i] - q[i - 1] == 1) {
                    ans++;
                } else {
                    ans = 0;
                    last = q[i];
                }
                if (ans > mx) {
                    mx = ans;
                    l = last;
                    r = q[i];
                }
            }
            cout << l << " " << r << endl;
        }
    }
    return 0;
}

 

题目大意: 一颗有根树,有n个顶点,一个字符串s,s又W和B组成,W表示该白色,B代表黑色,字符串中的每个字符表示每个节点的颜色,一个数组a,a2---an一共n个数,ai就是i节点的父节点,子树的黑色节点和白色节点数量相同则称该子树为平衡树,求该有根树的子树中有多少个平衡树.

思路:首先根据数组a建图,先预处理用-1表示白色,1表示黑色,如果该子树是平衡树的话,则节点值之和为0,dfs跑一遍,把每个子树的值赋给该子树的根节点,最后遍历所有节点,如果该节点的值为0,则ans++,最后输出ans即可。

(因为是多组输入,所以记得存图的数组和存节点值的数组清空)

#include<bits/stdc++.h>

using namespace std;

const int N=4e3+5;

vector<int>G[N];

int n;
int a[N],dp[N];
string s;

void dfs(int x)
{
    for(int i=0;i < G[x].size();i++)
    {
        int next=G[x][i];
        dfs(next);
        dp[x] += dp[next];
    }
}

int main()
{
    int tt;
    cin>>tt;
    while(tt--)
    {
        cin>>n;
        for(int i=0;i<=n;i++) G[i].clear();

        for(int i=2;i<=n;i++)
        {
            cin>>a[i];
            G[a[i]].push_back(i);
        }

        cin>>s;
        s=' '+s;
        memset(dp,0,sizeof dp);
        for(int i=1;i<s.size();i++)
        {
            if(s[i]=='B') dp[i]=1;
            else dp[i]=-1;
        }
        dfs(1);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(dp[i] == 0)ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值