2023/02/14刷题

B. Kuriyama Mirai's Stones

链接

B. Kuriyama Mirai's Stones

这是一个前缀和问题,分别求一下原数组的前缀和和排序后数组的前缀和然后按照询问输出就可以

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long

using namespace std;
const int N = 100005;

int s1[N], s2[N];
signed main () {
    ios::sync_with_stdio(false);
    int n;
    cin >> n;

    int a[N];
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        s1[i] = s1[i - 1] + a[i]; //原数组的前缀和存在s[1]里面
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; i++) {
        s2[i] = s2[i - 1] + a[i]; //排序后的前缀和存在s[2]里面
    }
    int m;
    cin >> m;
    while (m--) {
        int x, l, r;
        cin >> x >> l >> r;
        if (x == 1) { //x==1询问s1数组

            cout << s1[r] - s1[l - 1] << '\n';
        } else {
            //x==2询问s2数组

            cout << s2[r] - s2[l - 1] << '\n';
        }









    }




    return 0;
}

C. Ternary XOR

链接

C. Ternary XOR

这个题按照题目要求将一个数分成两个数,并且让构造的这两个数中最大的哪个是最小的,我们分别分析一下

  1. 0两边最小可以分为0,0
  2. 1两边最小可以分为1,0
  3. 2两边最小可以分为1,1,还可以分为2,0

我们先尽可能的平均分配两个数,这样可以保证两个数都较小,当必须有一个大于另外一个的时候,就假设第一个是最大的,当第一个大于第二个的时候,将剩下的所有的s[i]的分配贪心的最大分配给第二个数,这样才能保证得到的max(a,b)最小

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long

using namespace std;

signed main () {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        int n;
        string s;
        cin >> n >> s;//读入
        int flag = 0; //0代表先平均分配.1代表a已经大于b了将大的全部分配给b
        string a, b;
        for (int i = 0; i < n; i++) {
            if (flag == 0) {//一开始平均分配
                if (s[i] == '2') {
                    a = a + '1';
                    b = b + '1';
                } else if (s[i] == '1') {
                    //知道出现1分配不均,让flag=1;
                    a = a + '1';
                    b = b + '0';
                    flag = 1;
                } else {
                    a = a + '0';
                    b = b + '0';
                }


            } else {//当flag==2贪心的将最大的分配给b
                if (s[i] == '2') {
                    a = a + '0';
                    b = b + '2';
                } else if (s[i] == '1') {
                    a = a + '0';
                    b = b + '1';
                } else {
                    a = a + '0';
                    b = b + '0';
                }

            }


        }
        cout << a << '\n' << b << '\n'; //打印结果



    }






    return 0;
}

C. Boats Competition

链接

C. Boats Competition

这个问题需要用到双指针,直接直接枚举每种重量的人数,反正最大的重量只有100,用双重循环枚举2到100里面的所有可以组队的人数的最大值打印结果

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long

using namespace std;

signed main () {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    int a[55];
    while (t--) {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i]; //读入数据
        }

        sort(a + 1, a + n + 1); //给数组排序,便于一会双指针遍历
        int res = 0;
        for (int s = 2; s <= 102; s++) { //重量2-100
            int l = 1, r = n; //l指向左端,r指向右端
            int cnt = 0; //计数器
            while (l < r) {
                if (a[l] + a[r] > s) { //当[l]+a[r]大于s时,就让r--这样可以让和减小,再进行判断
                    r--;

                } else if (a[l] + a[r] < s) { //当[l]+a[r]小于s时,就l++这样可以让和增加,再进行判断
                    l++;
                } else if (a[l] + a[r] == s) { //当[l]+a[r]==s时,让l++,r--表示这一组数以后不会再被遍历了
                    cnt++;//同时让cnt++;

                    l++;
                    r--;

                }
                res = max(res, cnt); //每次更新最大值






            }




        }
        cout << res << '\n';


    }




    return 0;
}

D. Even-Odd Game

链接

D. Even-Odd Game

这个题也是补的,是一个博弈论的内容,看了别人的思路就是两个人互博,如果当前数字可以给自己加分的话,就直接那拿走,如果当前的数字不能给自己加分也拿走(因为不能让对方拿走加分),从最大的开始枚举就可以了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long

using namespace std;
const int N = 200000 + 5;
int a[N];

signed main () {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> a[i];//读入数据

        }
        sort(a, a + n);//排序
        int sum_a = 0, sum_b = 0;//定义sum_a和sum_b;
        int flag = 0;//控制当前给a还是b
        for (int i = n - 1; i >= 0; i--) {
            if (flag % 2 == 0 && a[i] % 2 == 0) {//如果当前是偶数并且轮到a了就让a拿走

                sum_a = sum_a + a[i];
            }
            if (flag % 2 == 1 && a[i] % 2 == 1) {//如果当前是奇数,并且轮到b了就让b拿走
                sum_b = sum_b + a[i];
            }
            flag++;

        }
        if (sum_a == sum_b) {//比较一下然后打印结果

            cout << "Tie" << '\n';
        } else if (sum_a > sum_b) {
            cout << "Alice" << '\n';
        } else {
            cout << "Bob" << '\n';

        }

    }





    return 0;
}

A. Regular Bracket Sequence

链接

A. Regular Bracket Sequence

这个题原来没看清楚条件,导致想了好久,后来发现整个字符串就只有一对括号(),剩下的都是?------这样答案就很明显了,如果字符串长度为n的话只有s[0]出现')'或者s[len-1]出现'(',才会导致不能生成符合规则的括号序列,其他情况可以发现都是可以的

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long
#define yes cout<<"YES"<<'\n'
#define no     cout<<"NO"<<'\n'

using namespace std;

signed main () {
//ios::sync_with_stdio(false);
    int t;
    cin >> t;

    while (t--) {
        string s;
        cin >> s;
        if ((int)s.size() % 2 == 1) { //长度为奇数直接打印no
            no;
            continue;
        }

        if (s[0] == ')' || s[s.size() - 1] == '(') { //如果满足这两种情况的其中一中打印no

            no;

        } else //剩下的情况打印yes

        {
            yes;
        }








    }




    return 0;
}

B. Young Explorers

B. Young Explorers

这个题也是补的,题目就是说只有团队的人数满足>=每个人的e_i的值才能组队出去,求这样组队能组多少队(可以留人在营地).原来自己想的做法一直超时,现在借鉴了一下啊别人的代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_set>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <sstream>
#include <queue>
#define int long long

using namespace std;

const int N = 200005;
int a[N];
//int st[N];
signed main () {
//    ios::sync_with_stdio(false);
    int t;
    scanf("%lld", &t);

    while (t--) {

        int n;
        scanf("%lld", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }//读入数据

        sort(a + 1, a + n + 1);
//排序
        int res = 0;//储存结果
        int cnt = 0;//用来计数
        for (int i = 1; i <= n; i++) {
            cnt++;//先让cnt++,
            if (cnt == a[i]) {//然后判断当前的cnt有没有等于当前的a[i],如果等于了,就让这几个人一组,
                //然后让cnt清零继续计数
                //每次到达a[i]就计数可以保证最小人数

                res++;
                cnt = 0;
            }


        }
        printf("%lld\n", res);//打印结果




        //        st[i]=st[i-1]+st[i];
        //
        //        res=res+st[i]/i;
        //        st[i]=st[i]%i;

    }


//




    return 0;
}
posted @ 2023-02-18 17:19  harper886  阅读(14)  评论(0编辑  收藏  举报