Canada Cup 2016 A,B,C,D,E

【A】左右扫一遍,统计出和扫描方向不同的括号个数,最后求个和就是答案了。

【复杂度】O(len)

【B】水题,读清楚题是关键。

【复杂度】O(1)

【代码】

//
//Created by just_sort 2016/10/24
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
const int maxn = 200005;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

LL n;
char c;

int main()
{
    while(scanf("%I64d%c",&n,&c)!=EOF)
    {
        getchar();
        LL sum = 0;
        sum = ((n-1)/4)*16;
        LL t = n%4;
        if(t % 2 == 0){
            sum += 7;
        }
        if(c == 'f') sum += 1;
        if(c == 'e') sum += 2;
        if(c == 'd') sum += 3;
        if(c == 'c') sum += 6;
        if(c == 'b') sum += 5;
        if(c == 'a') sum += 4;
        cout<<sum<<endl;
    }
}

【C】给了一个字符数为27的字符串,这个字符串表示它是一个2*13的字符矩阵的一个通路,其中相邻的两个字符可以直接相邻也可以一个角相邻。

【解题方法】一个最关键的信息就是那个出现了两次的字符串,很容易发现只有当出现两次的字符串的左右位置相差>1的时候才有解,那么字符串左右位置之间的字符需要放到尾部,剩下的顺序放就可以了。

【复杂度】O(27)

【代码】

char a[30];
char da[2][13];
int v[30];

int main()
{
    while(scanf("%s", a) != EOF)
    {
        memset(v, 0, sizeof(a));
        int len = 27;
        int l = -1, r = -1;
        char two;
        for(int i = 0; i < len; i++)
        {
            v[a[i]-'A']++;
            if(v[a[i]-'A'] == 2) two = a[i];
        }
        for(int i = 0; i < len; i++)
        {
            if(a[i] == two)
            {
                if(l == -1) l = i;
                else r = i;
            }
        }
        //cout<<l<<" "<<r<<endl;
        if(r - l == 1){
            printf("Impossible\n");
            continue;
        }
        int ans = (r -l -1)/2;
        da[0][12-ans] = two;
        for(int i = l + 1; i < len + l + 1; i++)
        {
            int x;
            if(i == r) continue;
            if(i >= len) x = i - len;
            else x = i;
            ans--;
            if(ans >= 0) da[0][12-ans] = a[x];
            else if(ans < 0 && ans >= -13) da[1][13+ans] = a[x];
            else if(ans < -13) da[0][-14-ans] = a[x];
        }
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 13; j++)
                printf("%c",da[i][j]);
            printf("\n");
        }
    }
}

【D题意】给你n 个队伍,你的队伍是第一个队伍,每个队伍有气球数量,和最大数量。如果气球数量多于最大数量,你就会飞走,无法进行排名!你现在可以给你别的队伍气球,使得他们飞走,从而使你的排名尽量靠前!问你的最好名次?

【解题方法】

把比Limak队的气球数多的队伍都放入优先队列中,优先队列按照队伍还有几个球才能飞起,从小到大排序.剩下的对放入数组中,按照气球数从小到大排序.取出队列第一个元素,判断Limak的气球数是否能够让其飞起,若是,则队伍淘汰,更新Limak的气球数,把数组中比Limak对多的气球放入优先队列中,循环操作。

【代码】

struct node{
    LL t, w;
    bool operator<(const node &rhs) const{
        return w - t + 1 > rhs.w - rhs.t + 1;
    }
};
bool cmp1(const node &a, const node &b)
{
    return a.t > b.t;
}
vector<node>v;
priority_queue<node>q;
int n;

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        LL t, w;
        while(!q.empty()) q.pop();
        v.clear();
        scanf("%I64d%I64d",&t,&w);
        for(int i = 1; i < n; i++)
        {
            LL x, y;
            scanf("%I64d%I64d",&x,&y);
            if(x > t) q.push(node{x,y});
            else v.push_back(node{x,y});
        }
        sort(v.begin(),v.end(),cmp1);
        int ans = q.size()+1;
        int l = 0;
        while(!q.empty())
        {
            node cur = q.top();
            if(cur.w - cur.t + 1 <= t)
            {
                t -= (cur.w - cur.t + 1);
                q.pop();
            }
            else{
                break;
            }
            for(l = l; l < v.size(); l++){
                if(v[l].t > t) q.push(v[l]);
                else break;
            }
            ans = min(ans, (int)q.size() + 1);
        }
        cout<<ans<<endl;
    }
}

【E】留坑,后续补。网上唯一的一篇blog,我还看不懂。 http://blog.csdn.net/xl2015190026/article/details/52900297

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值