比赛1

来源:互联网 发布:大学生网络危害的案例 编辑:程序博客网 时间:2024/05/02 00:37

codeforce 558A Lala Land and Apple Trees

问题描述:

Amr lives in Lala Land. Lala Land is a very beautiful country that is located on a coordinate line. Lala Land is famous with its apple trees growing everywhere.


Lala Land has exactly n apple trees. Tree number i is located in a position xi and has ai apples growing on it. Amr wants to collect apples from the apple trees. Amr currently stands in x = 0 position. At the beginning, he can choose whether to go right or left. He'll continue in his direction until he meets an apple tree he didn't visit before. He'll take all of its apples and then reverse his direction, continue walking in this direction until he meets another apple tree he didn't visit before and so on. In the other words, Amr reverses his direction when visiting each new apple tree. Amr will stop collecting apples when there are no more trees he didn't visit in the direction he is facing.

What is the maximum number of apples he can collect?
Input
The first line contains one number n (1 ≤ n ≤ 100), the number of apple trees in Lala Land.

The following n lines contains two integers each xi, ai ( - 105 ≤ xi ≤ 105, xi ≠ 0, 1 ≤ ai ≤ 105), representing the position of the i-th tree and number of apples on it.

It's guaranteed that there is at most one apple tree at each coordinate. It's guaranteed that no tree grows in point 0.

Output
Output the maximum number of apples Amr can collect.

Sample Input
Input
2
-1 5
1 5
Output
10
Input
3
-2 2
1 4
-1 3
Output
9
Input
3
1 9
3 5
7 10
Output

9

解题思路:

先在输入时将正负苹果树分开,计算两边的苹果总数,再对两边苹果树从小到大排序。判断两边树相等,或大于或小于,或相差数目为一,分别讨论。

AC代码:

#include <cstdio>#include <iostream>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int maxn=100000+5;struct Node{    int x;    int num;} node[maxn];bool cmp(Node e1, Node e2){    return e1.x < e2.x;}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int left = 0;        int right = 0;        int sum1 = 0;        int sum2 = 0;        for(int i = 1; i <= n; i++)        {            scanf("%d %d", &node[i].x, &node[i].num);            if(node[i].x < 0)            {                left++;                sum1+= node[i].num;            }            else            {                right++;                sum2 += node[i].num;            }        }        sort(node+1, node+1+n, cmp);        int step1, step2;        int sum3, sum4, sum;        if(left==0 && right!=0)        {            printf("%d\n", node[1].num);        }        else if(left != 0 && right == 0)        {            printf("%d\n", node[n].num);        }        else if(abs(right-left)==1||(right==left))        {            printf("%d\n", sum1+sum2);        }        else if(left > right)        {            step1= left - right;            sum3 = sum1 + sum2;            for(int i = 1; i <= step1; i++)            {                sum3 -= node[i].num;            }            sum4 = sum1 + sum2;            for(int i = 1; i <= step1 - 1; i++)            {                sum4 -= node[i].num;            }            printf("%d\n", max(sum3, sum4));        }        else if(left < right)        {            step2 = right - left;            sum3 = sum1 + sum2;            for(int i = n;i > n - step2;i--)            {                sum3 -= node[i].num;            }            sum4 = sum1 + sum2;            for(int i = n;i > n - step2 + 1;i--)            {                sum4 -= node[i].num;            }            printf("%d\n", max(sum3, sum4));        }    }    return 0;}

codeforce 558B Amr and The Large Array


问题描述:
Amr has got a large array of size n. Amr doesn't like large arrays so he intends to make it smaller.

Amr doesn't care about anything in the array except the beauty of it. The beauty of the array is defined to be the maximum number of times that some number occurs in this array. He wants to choose the smallest subsegment of this array such that the beauty of it will be the same as the original array.

Help Amr by choosing the smallest subsegment possible.
Input

The first line contains one number n (1 ≤ n ≤ 105), the size of the array.

The second line contains n integers ai (1 ≤ ai ≤ 106), representing elements of the array.
Output

Output two integers l, r (1 ≤ l ≤ r ≤ n), the beginning and the end of the subsegment chosen respectively.

If there are several possible answers you may output any of them.
Sample test(s)
Input

5
1 1 2 2 1

Output

1 5

Input

5
1 2 2 3 1

Output

2 3

Input

6
1 2 2 1 1 2

Output

1 5

Note

A subsegment B of an array A from l to r is an array of size r - l + 1 where Bi = Al + i - 1 for all 1 ≤ i ≤ r - l + 1

解题思路:这道题要让你找串中数目最多元素的所在的最小区间。分为两边,先找到出现次数最多的元素,并记录位置,找到即元素出现次数做多,即区间长度最小的元素。
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1000000+10;int cnt[maxn];//记录每个元素出现的次数int p1[maxn];//记录每个数第一次出现的位置int main(){    int n,a;    while(scanf("%d",&n) != EOF)    {        memset(cnt,0,sizeof(0));        memset(p1,0,sizeof(0));        int l = 0,r = 0,max_cnt = 0,min_dist = 0;        for(int i = 0;i < n;i++)        {            scanf("%d",&a);            if(!cnt[a])            {                p1[a] = i;            }            cnt[a]++;            if(max_cnt < cnt[a])            {                max_cnt = cnt[a];                l = p1[a];                r = i;                min_dist = i - p1[a];            }            if(max_cnt == cnt[a] && i - p1[a] < min_dist)//当最多出现次数与当前cnt[a]相同时,取区间最小,并更新            {                min_dist = i - p1[a];                l = p1[a];                r = i;            }        }        printf("%d %d\n",l + 1,r + 1);    }    return 0;}

codeforce 558C Amr and Chemistry


问题描述:
Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment.

Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals together, but all the chemicals volumes must be equal first. So his task is to make all the chemicals volumes equal.

To do this, Amr can do two different kind of operations.

Choose some chemical i and double its current volume so the new volume will be 2ai
Choose some chemical i and divide its volume by two (integer division) so the new volume will be
Suppose that each chemical is contained in a vessel of infinite volume. Now Amr wonders what is the minimum number of operations required to make all the chemicals volumes equal?

Input
The first line contains one number n (1 ≤ n ≤ 105), the number of chemicals.

The second line contains n space separated integers ai (1 ≤ ai ≤ 105), representing the initial volume of the i-th chemical in liters.

Output
Output one integer the minimum number of operations required to make all the chemicals volumes equal.

Sample Input
Input
3
4 8 2
Output
2
Input
3
3 5 6
Output
5

解题思路:

给你若干个数,对每个数都可以进行除或者乘的操作。  3/2=1,问 最少 多少步操作,可以让所有数字都相等。

首先如果都变成一个数字,那这个数字肯定是小于等于这些数字里的最大的那个的。

思路:可以除以二 或者 乘以二,就相当于位运算的右移和左移。用两个数组,vis 数组, cnt 数组。刚开始都初始化为0; vis[i] 表示 i 这个数可以由几个数转化而来,cnt[i] 表示题目给出的 n 个数全部转化为 i 需要的操作数。

首先遍历数组找到 ai 的最大值记为 MAX,那么所有数转化的上界就是 MAX,因为如果最终转化的数如果大于MAX,那么所有值都要转化为大于MAX的那个数,很明显这不是最后的答案。

把一个数表示为二进制数,

1、如果最低位是0,那么这个数右移一位(除以2),再左移一位(乘以2),就得到原来的数

2、如果最低位是1,那么这个数右移一位(除以2),再左移一位(乘以2),得不到原来的数

那么:

3要转化为8,最少需要4步操作,先除以2,再乘以2,再乘以2,再乘以2

2转化为8,最少需要2步操作,先乘以2,再乘以2

处理一个数 ai:

1、对 ai 执行左移操作,记录 ai 通过左移能够得到的数字,上限为MAX,vis 数组加1,cnt数组记录步数

2、对 ai 执行右移操作,直到 ai 为0

若 ai 的最低位为1,右移一步之后,进行左移,上限为MAX,维持vis数组和cnt数组

若 ai 的最低位为0,右移一步,维持vis数组和cnt数组

这样我们就把一个数的所有情况都处理出来了,并且是最少的操作数。

最后遍历数组找 vis[i] 为n,并且操作数最小。

AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 200000 + 10;const int INF = 0xffffff;int a[maxn],cnt[maxn],p[maxn];//cnt[i]数组中某个数到达i那么cnt[i]++,最终判断哪些数是所有数可以到达的int main(){    int n;    while(scanf("%d",&n) != EOF)    {        int Max = 0;        for(int i = 0;i < n;i++)  //找出每个数经过规则可以到达的数           {            scanf("%d",&a[i]);            Max = max(Max,a[i]);        }        memset(cnt,0,sizeof(cnt));        for(int i = 0;i < maxn;i++)        {            int u = a[i];            int ok = 1;            while(u != 0)            {                cnt[u]++;                if(ok) //如果这个数是一个奇数,那么它整除2后的结果需要再去一直扩大2倍,得到新的可以到达的数。                   {                    int v = u;                    while(v < Max)                    {                        v = v * 2;                        cnt[v]++;                    }                }                if(u % 2) ok = 1;                else    ok = 0;                u = u / 2;            }        }        int x = 0;        for(int i = 1;i <= maxn;i++)            if(cnt[i] == n)                p[x++] = i;//将每个都可以到达的数字挑出来放到p[x++]中        int ans = INF;        for(int k = 0;k < x;k++)        {            int res = 0;            for(int i = 0;i < n;i++)            {                int u = a[i];                int ok = 1;                int count = 0,tmp = 0;    //贪心求最小每个数到达目标数的最小步数 ,方法同上面求每个数可以到达的数一样                   while(u != p[k])                {                    if(ok)                    {                        int v = u;                        while(v < p[k])                        {                            v = v * 2;                            tmp++;                        }                        if(v == p[k])                            break;                    }                    if(u % 2)                        ok = 1;                    else ok = 0;                    u = u / 2;                    count++;                    tmp = count;                }                res += tmp;            }            ans = min(ans,res);        }        printf("%d\n",ans);    }    return 0;}

0 0
原创粉丝点击