zoukankan      html  css  js  c++  java
  • Codeforces Round #223 (Div. 2) 题解

    A.Sereja and Dima

    题意:有一列数,有A,B两个人,每个人只会拿数组两侧中大的那个数,问这样拿完以后每个人的价值和分别为多少

    思路:直接按题意模拟

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1007;
    int a[maxn];
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
        }
        int cnt = 1;
        int i = 1, j = n;
        int ansx = 0, ansy = 0;
        while(cnt <= n){
            if(a[i] <= a[j]){
                if(cnt & 1) ansx +=a[j];
                else ansy += a[j];
                j--;
            }
            else {
                if(cnt & 1) ansx += a[i];
                else ansy += a[i];
                i++;
            }
            cnt++;
        }
        printf("%d %d
    ",ansx,ansy);
        return 0;
    }
    View Code

    B. Sereja and Stairs

        题意:给n个数,让你从中选出一些数,可以构造一个先严格上升,在严格下降的数列,是数列长度最长,打印数列

        思路:把每个数都标记一下,从小到大打印一遍所有值,最大值,然后把剩下的数在打印一次,不打印最大值

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 +7;
    int stk[maxn];
    int top;
    int mp[5005];
    int main()
    {
        int n;
        scanf("%d", &n);
        map<int,int> mp;
        int maxe = -1;
        for(int i = 1; i <= n; i++) {
            int x;
            scanf("%d", &x);
            mp[x] ++;
            maxe = max(maxe , x);
        }
        for(int i = 1; i <= maxe; i++){
            if(mp[i]){
                stk[++top] = i;
                mp[i]--;
            }
        }
        for(int i = maxe - 1; i; i--) {
            if(mp[i]) {
                stk[++top] = i;
            }
        }
        printf("%d
    ",top);
        for(int i = 1; i <= top; i++) {
            if(i > 1)printf(" ");
            printf("%d",stk[i]);
        }
        puts("");
        return 0;
    }
    View Code

    C. Sereja and Prefixes

        题意:有两种操作,第一种操作是在数组最后面加入x,第二种操作是把数组前L个复制x次,有m次询问,每次询问回答数组中第i个数是几

        思路:1操作时直接插入到数组中,在插入2操作时,标记一下这个2操作,每个位置都记录插入了多少个数,如果询问的时候,二分答案,如果是1操作的数,直接打印插入的数,如果是2操作,就在此递归之前的区间,直到找到1操作

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    const int maxn = 1e6 + 7;
    int a[maxn];
    int kind[maxn],t[maxn];
    LL len[maxn];
    int n;
    int solve(LL x)
    {
        int id = lower_bound(len + 1, len + 1 + n, x) - len;
    //    printf("test %d
    ",id);
        if(kind[id] == 1){
            return a[id];
        }
        else {
            return solve((x - len[id - 1] - 1) % a[id] + 1);
        }
    }
    int main()
    {
        scanf("%d",&n);
        LL nowlen = 0;
        for(int i = 1; i <= n; i++) {
            int op, val;
            scanf("%d%d", &op, &val);
            if(op == 1) {
                kind[i] = 1;
                a[i] = val;
                len[i] = len[i - 1] + 1;
            }
            else{
                int time;
                scanf("%d", &time);
                kind[i] = 2;
                t[i] = time;
                a[i] = val;
                len[i] = len[i - 1] + time * val;
            }
        }
        int m ;
        scanf("%d", &m);
        while(m--) {
            LL x;
            scanf("%lld", &x);
            printf("%d ",solve(x));
        }
        return 0;
    }
    View Code

    D. Sereja and Tree

        题意:给出n和m(7000),带表一个n层的树和m次操作,树的结构是二叉树,如果b的2的某个次方,那b就有2个儿子,不然只有一个儿子,每个节点由(a,b)组成,a表示的是层数,b表示的是该节点在这一层的位置,有两种操作,1:给出t,l,r, x,表示在第t层[l,r]节点上添加一个数x;2:给出a,b,要求计算节点(a,b)以及它所有的孩子节点中共有多少中数字(重复不算)。

        思路:因为n和m都只有7000,所以直接n2暴力就可以出答案

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 7007;
    const int maxe = 200000;
    struct node
    {
        int l, r, val;
    };
    vector<node>a[maxn];
    int ll[maxe], rr[maxe];
    set<int> mp;
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        ll[1] = 1, rr[1] = 2;
        int now = 1, cnt = 3;
        ll[1] = 1; rr[1] = 2;
        for (int i = 2; i < maxe; i++) {
            if ((1 << now) == i) {
                now++;
                ll[i] = cnt++;
            }
            else ll[i] = -1;
            rr[i] = cnt++;
        }
        for(int i = 1; i <= m; i++) {
            int op;
            scanf("%d", &op);
            if(op == 1){
                int t;
                node as;
                scanf("%d%d%d%d", &t, &as.l, &as.r, &as.val);
                a[t].push_back(as);
            }
            else {
                int L, R;
                scanf("%d%d", &L, &R);
                mp.clear();
                int l = R, r = R;
                for(int j = L; j <= n; j++) {
    //                printf("j == %d %d l==%d r==%d
    ",j,a[j].size(),l,r);
                    for(int k = 0; k < a[j].size(); k++) {
    //                    printf("aaa %d a[j][k].l==%d r==%d a[i].[
    ",k);
                        if(a[j][k].l <= r && a[j][k].r >= l)mp.insert(a[j][k].val);
                    }
                    l = (ll[l] == -1 ? rr[l] : ll[l]);
                    r = rr[r];
                }
                printf("%d
    ",mp.size());
            }
        }
        return 0;
    }
    View Code

    E. Sereja and Brackets

        题意:给一段括号序列,有m次询问,每次回答[l,r]区间中有多少对括号匹配

        思路:用线段树直接维护,每个节点分别记录l,r,m,表示剩余没有匹配的左括号数量,剩余没有匹配的有括号数量,已经匹配的括号数量

        代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6 + 7;
    char a[maxn];
    int numl[maxn<<2],numr[maxn<<2],numm[maxn<<2];
    void pushup(int rt)
    {
        int minn = min(numl[rt << 1],numr[rt << 1 | 1]);
        numm[rt] = numm[rt << 1] + numm[rt << 1 | 1] + 2 * minn;
        numl[rt] = numl[rt << 1 | 1] + numl[rt << 1] - minn;
        numr[rt] = numr[rt << 1] + numr[rt << 1 | 1] - minn;
    }
    void build(int rt,int l,int r)
    {
        if(l == r){
            if(a[l] == '(')numl[rt] = 1;
            else numr[rt] = 1;
            return ;
        }
        int mid = (l + r) >> 1;
        build(rt << 1, l, mid);
        build(rt << 1 | 1, mid + 1,r);
        pushup(rt);
    }
    struct node
    {
        int l,r,m;
    };
    node query(int L,int R,int rt,int l,int r)
    {
    //    if(l > r)return 0;
        if(L <= l && r <= R){
            node as;
            as.l = numl[rt];
            as.r = numr[rt];
            as.m = numm[rt];
            return as;
        }
        int mid = (l + r) >> 1;
        if(R <= mid) return query(L, R, rt << 1, l, mid);
        else if(L > mid) return query(L, R, rt << 1 | 1, mid + 1, r);
        else{
            node as = query(L, R, rt << 1, l, mid);
            node qw = query(L, R, rt << 1 | 1, mid + 1, r);
            node ans;
            int minn = min(as.l, qw.r);
            ans.m = as.m + qw.m + 2 * minn;
            ans.l = as.l + qw.l - minn;
            ans.r = as.r + qw.r - minn;
            return ans;
        }
    }
    int main()
    {
        scanf("%s",a + 1);
        int n = strlen(a + 1);
        build(1, 1, n);
        int q;
        scanf("%d", &q);
        while(q--){
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d
    ",query(l,r,1,1,n).m);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    vue 自定义指令
    vue 插槽
    vue 菜单跳转 页面错乱
    vue项目中使用elementUI的el-tabs组件 浏览器卡死问题 解决办法
    vue 环境配置
    移动端页面 问题 注意事项
    定义全局 强制刷新指令
    手机端样式 处理
    手机访问电脑本地开发的页面
    百度AI
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/10412149.html
Copyright © 2011-2022 走看看