codeforce 401 div2 ABCED

codeforce 401 div2 题目链接

A - Shell Game (思维)

Descriprition

给 0,1,2, 3个盒子 ,盒子按照 奇数次移动时,0与1 交换位置, 偶数次移动时1与 2 交换位置, 告诉小球n 次移动后 最后在 盒子中的位置, 求小球初始时放入位置


Solution

显然 移动 是有周期的,周期为6


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[7][3]={{0,1,2},{1,0,2},{1,2,0},{2,1,0},{2,0,1},{0,2,1},{0,1,2}};
int main()
{
  long long  n,x;
  long long a1,a2,a3;
  scanf("%lld %lld",&n,&x);

  n=n%6;
  printf("%d\n",a[n][x]);
  return 0;
}

B - Game of Credit Cards (贪心)

Descriprition

a与b 玩游戏,每个人 给 n 个数,每回合两个人各出一个数,数 小的人 输一局
问b 最少能 输几局, 最多 能赢几局


Solution

将数 从小到大 排序,比较
最少输的局数,尽可能平局或胜利
最多赢的局数 ,尽可能胜利


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int n;
int a[N],b[N];
char s1[N],s2[N];
int main()
{
   cin>>n>>s1>>s2;
  for(int i=0;i<n;i++)
  {
      a[i]=s1[i]-'0';
      b[i]=s2[i]-'0';
  }
  sort(a,a+n);
  sort(b,b+n);
  int cnt1=0,cnt2=0;   // 牌的指针
  int ans1=0,ans2=0;
  while(cnt1<n&&cnt2<n)
  {
      if(a[cnt1]<=b[cnt2])
      {
          cnt1++;
          cnt2++;
      }
      else cnt2++;
  }
    ans1=n-cnt1;
   cnt1=0,cnt2=0;
   while(cnt1<n&&cnt2<n)
  {
      if(a[cnt1]<b[cnt2])
      {
          ans2++;
          cnt1++;
          cnt2++;
      }
      else cnt2++;
  }
  printf("%d\n%d\n",ans1,ans2);

    return 0;
}

C - Alyona and Spreadsheet (dp)

Descriprition
给n行m列的矩阵,每次 查询 (l,r) 从 l 行到 r 行, 是否存在某一 j 列 保持 连续的 不下 降序列,即 ai, j ≤ ai + 1, j for all i from l to r - 1


Solution
使用vector 原因 是 n*m<=1e5 , 要动态开辟数组
dp 思路, dp[i][j] 存放 该元素 向下的 最长 连续的 不下 降序列的长度

dp(i, j) = up(i + 1, j) + 1, ai, j < =ai + 1, j;
dp(i, j) = 1 otherwise.

num[i] 第i 行的 存在的最大 连续不下降序列的 长度;
num[i] =max(num[i] ,dp[i] [j]) (1=<j<=m)


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
vector< vector<int> >a;
vector< vector<int> >b;
//int num[N];
vector<int >num;
int n,m;

// b[i][j] 存放第i行第j列的 元素 在第j列向下 最长的连续不下降序列的 长度
// num[i]  第i 行的 存在的最大 连续不下降序列的 长度;
void dp()
{

    b.resize(n,vector<int >(m,0));

    num.resize(n,0);

    for(int i=0; i<m; i++)
        b[n-1][i]=1;
    num[n-1]=1;

    for(int i=n-2; i>=0; i--)
    {
        for(int j=0; j<m; j++)
        {
            if(a[i][j]<=a[i+1][j])
            {
                b[i][j]=b[i+1][j]+1;
            }
            else
                b[i][j]=1;
            num[i]=max(num[i],b[i][j]);
        }
    }

}

int main()
{

    int x,k;

    scanf("%d %d",&n,&m);
    // a.resize(n,vector<int>(m,0));

    for(int i=0; i<n; i++)
    {

        a.push_back( vector<int>() );
        for(int j=1; j<=m; j++)
        {
            scanf("%d",&x);
            a[i].push_back(x);
        }
    }
  /*  for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
            printf("%d ",a[i][j]);
        printf("\n");
    }*/

    dp();

    scanf("%d",&k);
    int l,r;
    for(int i=1; i<=k; i++)
    {
        scanf("%d %d",&l,&r);
        l--,r--;
        if(num[l]>=(r-l+1))
        {
            printf("Yes\n");
        }
        else
        {
            printf("No\n");
        }
    }
    return 0;
}

D - Cloud of Hashtags (字符串排序)

Descriprition

n个字符串, 保证从上到下,保持字典序(从小到大,可以相等), 可删去串的 任意长度的 后缀


Solution
从下往上遍历 去删除 不符合字典序的 后缀


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
string s1[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        cin>>s1[i];
    int i,j,k;
    int len1,len2,cnt;
    for( j=n-1; j>=1; j--)
    {
        i=j-1;
        if(s1[i]>s1[j])
        {

            len1=s1[i].size();
            len2=s1[j].size();
            cnt=-1;
            while(++cnt<=min(len1,len2))
            {

                if(s1[i][cnt]>s1[j][cnt])
                {
                    s1[i].erase(s1[i].begin()+cnt,s1[i].end());
                    break;
                }
            }
        }
    }

 /*
 * 提供另一种比较方法, 显然对于字典序的比较,
 * 当i位置 出现不同字母时,两个串字典序 必定会区分出大小
 * 在判断出是 字典序s[i]>s[i+1] 时,
 * 当两个串 出现不同字母时,必定是 i 串 出现 字典序较大的字母
 */
  /*    for(int i=n-2; i>=0; i--)

        {
            if(s[i]>s[i+1])
            {
                int l=max(s[i].size(),s[i+1].size());
                for(int j=0; j<l; j++)
                {

                    if(s[i][j]!=s[i+1][j])
                    {
                        s[i][j]='\0';
                        break;
                    }
                }
            }
        }
*/
    for(int i=0; i<n; i++)
    {
        cout<<s1[i]<<endl;
    }

    return 0;
}

E - Hanoi Factory (贪心+单调栈)

Descriprition

n个 圆环,给每个圆环的内径 a,外径 b,圆环高度 h,当 两个圆环的 b1<=b2, b1>a1
则 1环 可以落在 2 上面,高度叠加,求圆环相叠的最大高度


Solution

将所有环 按外径从大到小排序,外径相等时 在将内径从大到小排序
内径从大到小排序的原因:外径逐渐减小时,内径要尽可能小 才能叠加更多的环

单调栈,维护 第i 个环 进入时的最大高度
为什么符合单调栈 ,因为 当 第 i 个位置 不符合叠加条件是,显然后面的环也不符合叠加

此时符合栈的 后入先出 条件


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+10;
typedef struct
{
    int a,b,h;
} stu ;
stu p[N];

int cmp(stu x,stu y)
{
    if(x.b!=y.b)
        return x.b>y.b;
    else
        return x.a>y.a;
}
stack<stu>s;
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d %d %d",&p[i].a,&p[i].b,&p[i].h);
    }
    sort(p+1,p+1+n,cmp);
    
    long long  ans=0,sum=0;
  for(int i=1; i<=n; i++)
    {
        while(!s.empty()&&p[i].b<=s.top().a)
        {
            sum-=s.top().h;
            s.pop();
        }
        s.push(p[i]);
        sum+=p[i].h;
        ans=max(ans,sum);
    }
    printf("%lld\n",ans);

    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值