Codeforces Round #469 (Div. 2)(A-D)(水题 + 模拟 + 模拟 + 规律公式)

昨天下午4点场的CF,正好上完课喝着茶叶顶着打完了一场。巨开心的就是这场CF结束后蓝名了,美滋滋,继续努力~

A. Left-handers, Right-handers and Ambidexters

You are at a water bowling training. There are l people who play with their left hand, r people, who play with their right hand, and aambidexters, who can play with left or right hand.

The coach decided to form a team of even number of players, exactly half of the players should play with their right hand, and exactly half of the players should play with their left hand. One player should use only on of his hands.

Ambidexters play as well with their right hand as with their left hand. In the team, an ambidexter can play with their left hand, or with their right hand.

Please find the maximum possible size of the team, where equal number of players use their left and right hands, respectively.

Input

The only line contains three integers lr and a (0 ≤ l, r, a ≤ 100) — the number of left-handers, the number of right-handers and the number of ambidexters at the training.

Output

Print a single even integer — the maximum number of players in the team. It is possible that the team can only have zero number of players.

Examples
input
Copy
1 4 2
output
6

A题:左撇子l人,右撇子r人,双手都能用的a人,问一只左手和一只右手配对,总共多少人配成。

水题但是一开始上来有点慌,用了好多判断来写又繁琐又耽误时间。

int main()
{
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    if(a>=b){
        if(c<a-b) printf("%d\n", 2*(b+c));
        else printf("%d\n", (a+b+c)/2*2);
    }
    else {
        if(c<b-a) printf("%d\n", 2*(a+c));
        else printf("%d\n", (a+b+c)/2*2);
    }
}

结束后看其他人的代码,学长用的是将c分给a,b,谁少给谁,分完取min。排行榜大佬用的是swap得到a,b中较大的,然后和我一样的判断,不需要写两遍。CF第一题水题,应该追求速度和效率。但是个人做题较慢也是个问题。

B. Intercepted Message

Hacker Zhorik wants to decipher two secret messages he intercepted yesterday. Yeah message is a sequence of encrypted blocks, each of them consists of several bytes of information.

Zhorik knows that each of the messages is an archive containing one or more files. Zhorik knows how each of these archives was transferred through the network: if an archive consists of k files of sizes l1, l2, ..., lk bytes, then the i-th file is split to one or more blocks bi, 1, bi, 2, ..., bi, mi (here the total length of the blocks bi, 1 + bi, 2 + ... + bi, mi is equal to the length of the file li), and after that all blocks are transferred through the network, maintaining the order of files in the archive.

Zhorik thinks that the two messages contain the same archive, because their total lengths are equal. However, each file can be split in blocks in different ways in the two messages.

You are given the lengths of blocks in each of the two messages. Help Zhorik to determine what is the maximum number of files could be in the archive, if the Zhorik's assumption is correct.

Input

The first line contains two integers nm (1 ≤ n, m ≤ 105) — the number of blocks in the first and in the second messages.

The second line contains n integers x1, x2, ..., xn (1 ≤ xi ≤ 106) — the length of the blocks that form the first message.

The third line contains m integers y1, y2, ..., ym (1 ≤ yi ≤ 106) — the length of the blocks that form the second message.

It is guaranteed that x1 + ... + xn = y1 + ... + ymAlso, it is guaranteed that x1 + ... + xn ≤ 106.

Output

Print the maximum number of files the intercepted array could consist of.

Examples
input
Copy
7 6
2 5 3 1 11 4 4
7 8 2 4 1 8
output
3
B题:给定两个序列,相邻的可以合并,问上下经过各自的合并后,最多有几个对应相等的。

就直接模拟,谁少谁合并,相等就cnt++

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    for(int i=0; i<m; i++)
        scanf("%d",&b[i]);

    long long sum1=a[0],sum2=b[0];
    int p1=0,p2=0,cnt=0;


    while(p1<n && p2<m)
    {
        if(sum1 == sum2){
            cnt++;
            p1++;
            if(p1 < n) sum1 = a[p1];
            p2++;
            if(p2 < m) sum2 = b[p2];
        }
        else if(sum1 > sum2){
            p2++;
            if(p2 < m) sum2 += b[p2];
        }

        else if(sum1 < sum2){
            p1++;
            if(p1 < n) sum1 += a[p1];
        }
    }

    printf("%d\n",cnt);
}
C. Zebras

Oleg writes down the history of the days he lived. For each day he decides if it was good or bad. Oleg calls a non-empty sequence of days a zebra, if it starts with a bad day, ends with a bad day, and good and bad days are alternating in it. Let us denote bad days as 0 and good days as 1. Then, for example, sequences of days 001001010 are zebras, while sequences 101100101 are not.

Oleg tells you the story of days he lived in chronological order in form of string consisting of 0 and 1. Now you are interested if it is possible to divide Oleg's life history into several subsequences, each of which is a zebra, and the way it can be done. Each day must belong to exactly one of the subsequences. For each of the subsequences, days forming it must be ordered chronologically. Note that subsequence does not have to be a group of consecutive days.

Input

In the only line of input data there is a non-empty string s consisting of characters 0 and 1, which describes the history of Oleg's life. Its length (denoted as |s|) does not exceed 200 000 characters.

Output

If there is a way to divide history into zebra subsequences, in the first line of output you should print an integer k (1 ≤ k ≤ |s|), the resulting number of subsequences. In the i-th of following k lines first print the integer li (1 ≤ li ≤ |s|), which is the length of the i-th subsequence, and then li indices of days forming the subsequence. Indices must follow in ascending order. Days are numbered starting from 1. Each index from 1 to n must belong to exactly one subsequence. If there is no way to divide day history into zebra subsequences, print -1.

Subsequences may be printed in any order. If there are several solutions, you may print any of them. You do not have to minimize nor maximize the value of k.

Examples
input
Copy
0010100
output
3
3 1 3 4
3 2 5 6
1 7

C题:给定一个01串,定义以0为开头和结尾,01交替出现的串为斑马串。问可将原串分为几个斑马串,并输出任意一种组合方式。这道题一开始想的时候是想用构造的方式,可不管是优先配前置0还是优先配后置0都会出现一些问题。然后就当机了一段时间。后来改用二维 vector模拟,记录0 和 1 能放置的位置,有1却没有1的位置can = false,有0却没有0的位置另开一个子串。最后如果还有需要0的位置说明有串不以0为结尾。can = false;因为为了避免遍历vector找加入位置,所以选择了优先队列记录可放置0 1的位置。下来之后想了想队列就可以做不需要优先队列。因为是任意组合不是先输出较长的串。

priority_queue<int,vector<int>,greater<int> >p0;
priority_queue<int,vector<int>,greater<int> >p1;

char a[maxn];
vector<int >id[maxn];
bool vis[maxn];

int main()
{
    memset(vis, false, sizeof vis);
    int maxx = 0;
    bool can = true;
    scanf("%s",a);
    int lena = strlen(a);
    for(int i=0; i<lena; i++)
    {
        if(a[i] == '0')
        {
            if(p0.empty())
            {
                id[maxx].push_back(i);
                p1.push(maxx++);
            }
            else
            {
                int fir = p0.top();
                id[fir].push_back(i);
                p1.push(fir);
                p0.pop();
            }
        }
        else if(a[i] == '1')
        {
            if(p1.empty())
            {
                can =false;
                break;
            }
            else
            {
                int fir = p1.top();
                id[fir].push_back(i);
                p0.push(fir);
                p1.pop();
            }
        }
    }

    if(!p0.empty()) can = false;

    if(!can) printf("-1\n");
    else
    {
        printf("%d\n",maxx);
        for(int i=0; i<maxx; i++)
        {
            printf("%d ", id[i].size());
            for(int j=0; j<id[i].size(); j++)
                printf("%d%c",id[i][j]+1,j==id[i].size()-1?'\n':' ');
        }
    }
}
D. A Leapfrog in the Array

Dima is a beginner programmer. During his working process, he regularly has to repeat the following operation again and again: to remove every second element from the array. One day he has been bored with easy solutions of this problem, and he has come up with the following extravagant algorithm.

Let's consider that initially array contains n numbers from 1 to n and the number i is located in the cell with the index 2i - 1 (Indices are numbered starting from one) and other cells of the array are empty. Each step Dima selects a non-empty array cell with the maximum index and moves the number written in it to the nearest empty cell to the left of the selected one. The process continues until all n numbers will appear in the first n cells of the array. For example if n = 4, the array is changing as follows:

You have to write a program that allows you to determine what number will be in the cell with index x (1 ≤ x ≤ n) after Dima's algorithm finishes.

Input

The first line contains two integers n and q (1 ≤ n ≤ 10181 ≤ q ≤ 200 000), the number of elements in the array and the number of queries for which it is needed to find the answer.

Next q lines contain integers xi (1 ≤ xi ≤ n), the indices of cells for which it is necessary to output their content after Dima's algorithm finishes.

Output

For each of q queries output one integer number, the value that will appear in the corresponding array cell after Dima's algorithm finishes.

Examples
input
Copy
4 3
2
3
4
output
3
2
4

D题:有n个数间隔为1升序放置,每次最后的那个数会跳到最靠后的空白位置,知道充满前n个位置。完成后询问q次,编号为i的位置上是数字几

找规律后发现,从后往前的第一个数,第1 2 4 8次跳。即从后往前的第n个数,会在2*n-1次开始往前跳,每次跳的时候都是第k*(2*n-1)次。然后推公式得到结果。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e6+10;
const int mod = 1e9+7;
const double eps = 1e-8;
typedef long long LL;

int sgn(double x)
{
    if(fabs(x) < eps) return 0;
    else if(x > eps) return 1;
    else return -1;
}

LL qp(LL a, LL b)
{
    LL ans = 1;
    while(b > 0)
    {
        if(b&1)
            ans *= a;
        b >>= 1;
        a *= a;
    }

    return ans;
}

LL n, m;
int q;

LL ans(LL x)
{
    LL num = 2*(n-x) + 1;
    LL cnt = 0;
    LL mm = (n-1) / num;
    while(mm>0)
    {
        mm >>= 1;
        cnt++;
    }
    if(cnt == 0) return 2*x-1;
    LL step = num * qp(2, cnt-1);
    //printf("num:%I64d cnt:%I64d step:%I64d\n",num, cnt, step);
    LL y = 2*(n-step);
    return y;
}


LL ans2(LL y)
{
    if(y&1) return (y+1)/2;

    LL step = n - y/2;
    LL cnt = 0;
    LL mm = step;
    while(!(mm&1))
    {
        mm >>= 1;
        cnt++;
    }
    //printf("step: %I64d\n", step);
    LL num = step / qp(2, cnt);
    //printf("num: %I64d\n", num);
    LL ans = n - (num - 1) / 2;
    return ans;
}

int main()
{

    scanf("%I64d%d",&n ,&q);
    while(q--)
    {
        scanf("%I64d", &m);
        printf("%I64d\n", ans2(m));
    }
}

一开始推反了写了ans(),后来才发现要正过来计算结果蒙了半个小时才把公式倒过来,写出了ans2(),也是迷醉。


不管怎么说突然蓝名还是特别特别特别开心的。继续努力吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值