zoukankan      html  css  js  c++  java
  • Codeforces Round #561 (Div. 2)

    C. A Tale of Two Lands

    题意:

      给出 n 个数,问有多少点对(x,y)满足 |x-y| ≤ |x|,|y| ≤ |x+y|;

      (x,y) 和 (y,x) 表示一种答案;

    题解:

      数形结合;

      对于某数 x 查找满足条件 y 有多少个;

      ①x ≥ 0

        y ∈ [x/2 , 2x] ∪ [ -2x , -x/2];

      ②x < 0

        y ∈ [2x , -x/2] ∪ [-x/2 , -2x];

      特别注意临界值 x/2 处;

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int maxn=2e5+50;
     5 
     6 int n;
     7 int x[maxn];
     8 
     9 int F(int a,int b)///查找数组x中有多少数位于[a,b]之间
    10 {
    11     if(a > b)
    12         swap(a,b);
    13     int t1=lower_bound(x+1,x+n+1,a)-x;
    14     int t2=upper_bound(x+1,x+n+1,b)-x;
    15     return t2-t1;
    16 }
    17 ll Solve()
    18 {
    19     sort(x+1,x+n+1);
    20 
    21     ll ans=0;
    22     for(int i=1;i <= n;++i)
    23     {
    24         int a,b;
    25         if(x[i] >= 0)
    26             a=(x[i]+1)/2;
    27         else
    28             a=(x[i]-1)/2;///不能写成(x[i]-1)>>1;
    29         b=x[i]*2;///不能写成b=x[i]<<1;
    30         ans += F(a,b);
    31         ans += F(-a,-b);
    32         ans--;///减掉x[i]本身
    33     }
    34     return ans>>1;///重复计算,除以2
    35 }
    36 int main()
    37 {
    38     scanf("%d",&n);
    39     for(int i=1;i <= n;++i)
    40         scanf("%d",x+i);
    41     printf("%lld
    ",Solve());
    42 
    43     return 0;
    44 }
    View Code

    坑:

      负数使用右移符号出错;

      -2×2 ≠ -2<<1;

      左移,右移只可以用到正整数上;

      负数禁用位移运算;


    D. Cute Sequences

    题意:

      定义“Cute Sequences”,如果序列x满足 ∀i∈[2 , n] xi=xi1+xi2++x1+ri ≤ r≤ m),那么次序列为"Cute Sequences";

      现给出你 a,b,m ,让你构造一个序列,满足:

      ①x[1] = a , x[n] = b;

      ②n ≤ 50;

      ③此序列为"Cute Sequences";

    题解:

      定义数组val[]存储最终的值;

      看下面这段代码:

     1 ll sum=a;
     2 ll k=0;
     3 val[++k]=a;
     4 while(k <= 50)
     5 {
     6     if(val[k] >= b)
     7         break;
     8 
     9     val[++k]=sum+m;
    10     sum += val[k];
    11 }

      因为题目要求 k ≤ 50,所以,要先让其每次加最大的值 m ,找到使得 val[k] ≥ b 的最小的 k ;

      那么多的部分 val[k]-b 该怎么办呢?

       

      刚开始,每个数都会增加 m ,如果第 i 个数少加 x,有什么变化呢?

      先通过上述小范围的数据看一下规律;

      你会发现,如果第 i 个数少加 x,那么,对于第 j (j > i) 个数,就会少加2j-i-1x;

      这样的话,就可以通过前面的数少加 x 使得第 k 个数 val[k] 变为 b;

      不过在此之前你得确定 val[k] 可以减少为 b;

     1 bool isSat(int k)
     2 {
     3     memcpy(tmp+1,val+1,k*sizeof(ll));
     4     for(int i=2;i <= k;++i)
     5     {
     6         ll x=m-1;
     7         tmp[i] -= x;
     8         for(int j=i+1;j <= k;++j)///i之后的数依次减少2^(j-i-1)*x,累加x即可
     9             tmp[j] -= x,x += x;
    10         if(tmp[k] <= b)
    11             return true;
    12     }
    13     return tmp[k] <= b ? true:false;
    14 }

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define mem(a,b) memset(a,b,sizeof(a))
     5 const int maxn=2e5+50;
     6 
     7 int q;
     8 ll a,b,m;
     9 ll val[60];
    10 ll tmp[60];
    11 
    12 bool isSat(int k)
    13 {
    14     if(k == 1)
    15         return true;
    16 
    17     memcpy(tmp+1,val+1,k*sizeof(ll));
    18     for(int i=2;i <= k;++i)
    19     {
    20         ll x=m-1;
    21         tmp[i] -= x;
    22         for(int j=i+1;j <= k;++j)
    23             tmp[j] -= x,x += x;
    24         if(tmp[k] <= b)
    25             return true;
    26     }
    27     return false;
    28 }
    29 void Solve()
    30 {
    31     ll sum=a;
    32     ll k=0;
    33     val[++k]=a;
    34     while(k <= 50)
    35     {
    36         if(val[k] >= b)
    37             break;
    38 
    39         val[++k]=sum+m;
    40         sum += val[k];
    41     }
    42 
    43     if(k > 50 || !isSat(k))
    44     {
    45         printf("-1
    ");
    46         return ;
    47     }
    48 
    49     printf("%lld %lld",k,a);
    50     for(int i=2;i < k;++i)
    51     {
    52         ll d=val[k]-b;
    53         ll x=min(m-1,d/(1ll*1<<(k-i-1)));
    54 
    55         val[i] -= x;
    56         for(int j=i+1;j <= k;++j)
    57             val[j] -= x,x += x;
    58 
    59         printf(" %lld",val[i]);
    60     }
    61     if(k > 1)
    62         printf(" %lld
    ",b);
    63     else
    64         printf("
    ");
    65 }
    66 int main()
    67 {
    68 //    freopen("C:/Users/14685/Desktop/stdin&&stdout/contest","r",stdin);
    69     scanf("%d",&q);
    70     while(q--)
    71     {
    72         scanf("%lld%lld%lld",&a,&b,&m);
    73         Solve();
    74     }
    75     return 0;
    76 }
    View Code

    bug:

      61~64最后输出语句,晚上重新敲的时候将其放到了for()里:

     1 printf("%d %lld",k,a);
     2 for(int i=2;i <= k;++i)
     3 {
     4     if(i == k)
     5     {
     6         printf(" %lld
    ",b);
     7         return ;
     8     }
     9     ll d=val[k]-b;
    10     ll x=min(m-1,d/(1ll*1<<(k-i-1)));
    11 
    12     val[i] -= x;
    13     for(int j=i+1;j <= k;++j)
    14         val[j] -= x,x += x;
    15 
    16     printf(" %lld",val[i]);
    17 }

      一直是“Wrong answer on test 10”,debug了好一会,才发现,当 k = 1是,最后是有换行的;

      但是,放到for()里就缺少一个换行;

  • 相关阅读:
    寒假每日总结——2020.2.1
    亿级用户下的新浪微博平台架构读后感
    京东话费充值系统架构演讲读后感
    京东物流系统架构演讲中的最佳实践读后感
    京东上千页面搭建基石——CMS前后端分离演讲史读后感
    数据蜂巢架构演讲之路读后感
    关于SOA架构设计的案例分析下
    京东虚拟业务多维订单系统架构设计读后感
    在VUE-CLI 3下的第一个Element-ui项目(菜鸟专用)
    在vue-cli3中优雅的使用 icon
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10895792.html
Copyright © 2011-2022 走看看