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\n",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\n",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\n",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\n",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].[\n",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\n",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\n",query(l,r,1,1,n).m);
    }
    return 0;
}
View Code

 

posted @ 2019-02-21 14:09  啦啦啦天啦噜  阅读(223)  评论(0编辑  收藏  举报