zoukankan      html  css  js  c++  java
  • CodeForces Round #287 Div.2

    A. Amr and Music (贪心)

    水题,没能秒切,略尴尬。

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 const int maxn = 100 +10;
     6 int a[maxn], r[maxn], ans[maxn];
     7 
     8 int cmp(int i, int j) { return a[i] < a[j]; }
     9 
    10 int main()
    11 {
    12     //freopen("in.txt", "r", stdin);
    13 
    14     int n, k;
    15     scanf("%d%d", &n, &k);
    16     for(int i = 0; i < n; ++i) r[i] = i;
    17     for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
    18     sort(r, r + n, cmp);
    19     int sum = 0, cnt = 0;
    20     for(int i = 0; sum + a[r[i]] <= k && cnt < n; ++i)
    21     {
    22         sum += a[r[i]];
    23         ans[cnt++] = r[i];
    24     }
    25 
    26     printf("%d
    ", cnt);
    27     for(int i = 0; i < cnt - 1; ++i) printf("%d ", ans[i]+1);
    28     if(cnt) printf("%d
    ", ans[cnt-1]+1);
    29 
    30     return 0;
    31 }
    代码君

    B. Amr and Pins (找规律)

    题意:

    给出一个圆的半径 和 圆心的始末位置。每次操作只能绕圆周上的点旋转若干角度。求该圆从初位置到末位置最少的操作次数。

    分析:

    不妨设圆的半径为r,圆心在原点处。

    先看只旋转一次的情况,圆心所有可能位置构成的区域为  半径为2r的圆(除去圆心那点),也可理解为半径为(0, 2r]的圆环区域

    再看第二次旋转,其区域为半径在(2r, 4r]的圆环区域。  //这个不容易画图,自行脑补一下好啦

    以此类推。

    算法:

    所以我们可以先算出圆心始末位置间的距离d,然后根据d和直径2r的关系,最终答案为

     1 #include <cstdio>
     2 #include <cmath>
     3 
     4 int main()
     5 {
     6     //freopen("in.txt", "r", stdin);
     7 
     8     int r, x1, y1, x2, y2, ans;
     9     scanf("%d%d%d%d%d", &r, &x1, &y1, &x2, &y2);
    10     double d = sqrt((long long)(x1-x2)*(x1-x2) + (long long)(y1-y2)*(y1-y2));
    11     ans = (int)ceil(d / 2.0 / r);
    12     printf("%d
    ", ans);
    13 
    14     return 0;
    15 }
    代码君

    C. Guess Your Way Out! (模拟 LCA)

    题意:

    有一个树高为h的完全二叉树 和 一个目标叶子节点, 给出一种遍历方式(LRLRLR...)

    求在到达目标节点时,遍历节点的总数。(不包括目标节点)

    具体参见原文Guess Your Way Out!

    分析:

    以官方题解中的图为例。自己最开始对这道题没什么想法,所以后面的分析相当于题解的翻译。=_=||

    从树根开始走到最底端,到达节点X。

    如果X刚好是目标节点E,则得到结果为树高h。

    否则,找到X和E的 Least Common Ancestor (最小公共祖先)。在右子树遍历之前,一定会遍历完左子树中所有的节点 (图中用红色标出) ,从而退出,进入右子树。

    所以在到达右子树之前共遍历sum[h1] + h - h1,其中sum[h1]表示树高为h1的完全二叉树的节点个数。

    在进入右子树后,更新树高h、根节点编号、遍历的方向(L or R),重复刚才的过程。

     1 #include <cstdio>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 typedef long long LL;
     7 
     8 LL h, n, sum[55], ans = 0;
     9 vector<LL> anc1;
    10 
    11 int main()
    12 {
    13     //freopen("in.txt", "r", stdin);
    14 
    15     for(int i = 0; i <= 50; ++i) sum[i] = (1LL << (i+1)) - 1;
    16     scanf("%I64d%I64d", &h, &n);
    17     n += sum[h-1];  //转化成整个二叉树中的编号
    18     LL x = n;
    19     anc1.push_back(x);  //目标节点的所有祖先
    20     while(x != 1)
    21     {
    22         x /= 2;
    23         anc1.push_back(x);
    24     }
    25     //for(int i = 0; i < anc1.size(); ++i) printf("%I64d  ", anc1[i]);
    26 
    27     LL node = 1;
    28     bool choice = false;    //遍历防线(L or R)
    29 
    30     while(node != n)
    31     {
    32         vector<LL> anc2;    //当前叶子节点X的祖先
    33         for(int i = 0; i < h; ++i)
    34         {
    35             anc2.push_back(node);
    36             if(!choice) node = node * 2; else node = node * 2 + 1;
    37             choice = !choice;
    38         }
    39         if(n == node) { ans += h; break; }
    40         anc2.push_back(node);
    41         reverse(anc2.begin(), anc2.end());
    42         //for(int i = 0; i < anc2.size(); ++i) printf("%I64d  ", anc2[i]);
    43 
    44         for(int i = 1; i <= h; ++i) if(anc1[i] == anc2[i])
    45         {//find LCA
    46             ans += sum[i-1] + h - i + 1;
    47             h = i - 1;      //更新树高
    48             node = anc2[i-1];
    49             if((anc2[i]<<1) == node)    //更新根节点的编号 及 遍历方向
    50             {
    51                 node = anc2[i] * 2 + 1;
    52                 choice = false;
    53             }
    54             else
    55             {
    56                 node = (anc2[i] << 1);
    57                 choice = true;
    58             }
    59             break;
    60         }
    61     }
    62 
    63     printf("%I64d
    ", ans);
    64 
    65     return 0;
    66 }
    代码君
  • 相关阅读:
    #Leetcode# 541. Reverse String II
    PAT 甲级 1030 Travel Plan
    PAT 甲级 1029 Median
    bzoj 2002 [Hnoi2010]Bounce 弹飞绵羊
    jzoj 4243. 【五校联考6day1】c
    2019.02.23【NOIP提高组】模拟 A 组 总结
    【GDOI2013模拟1】病毒传播
    【GDOI2013模拟1】最短路
    【GDOI2013模拟1】删数字
    数列分块入门 6 总结
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4249319.html
Copyright © 2011-2022 走看看