一起来做题~欢乐赛2

A 新比赛,在眼前。

拿到这个题,我们来看,给一个数x,再给一个字符
如果是+,说明我们的x大于了我们的答案,也就是我们的答案在x的左侧;如果是-,说明x小于我们的答案,也就是我们的答案在x的右侧。
如果是=,说明我们的x等于x。
那么,我们将他画到横轴上,就是区间,区间重复最多的就是我们的答案。
下面是做题思路。
我想的就是将信息存下来,然后排个序,然后离散化,但是和雨巨的map比较一下,逊爆了。
来,学习一下。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <climits>
#include <map>

using namespace std;

int n;
map<int, int> b;
int main()
{
  cin >> n;
  while (n -- )
  {
    int x; char op[2];
    scanf("%d%s", &x, op);
    //公式b[L] ++, bp[R + 1] --
    if (*op == '+')
    {
      //当前结果大了,说明结果在左侧
      b[0] ++;
      b[x] --;//不包含当前数x
    }
    else if (*op == '-')
    {
      b[x + 1] ++;
      b[INT_MAX] --;
    }
    else
    {
      b[x] ++;
      b[x + 1] --;
    }
  }

  int ans = 0, sum = 0;
  for (auto it : b)
  {
    sum += it.second;
    ans = max(ans, sum);
  }

  cout << ans << "\n";
  
  return 0;
}

B 有人说,上周题还没做完……

线性DP,我们将给的数组用线性DP扫一下,将哪些能被用其他元素叠加所得得元素给标记一下,然后再查下表记个数就OK了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110, M = 25010;

int n;
int a[N];
int dp[M];

void work()
{
  cin >> n;
  for (int i = 1; i <= n; i ++ )
  {
    cin >> a[i];
  }
  memset(dp, -1, sizeof dp);
  dp[0] = 0;
  for (int i = 1; i <= n; i ++ )
    for (int j = a[i]; j <= M - 10; j ++ )
    {
      if (dp[j-a[i]] >= 0) dp[j] = max(dp[j], dp[j - a[i]] + 1);
    }

  // for (int i = 1; i <= 100; i ++ )
  //   cout << dp[i] << ' ';
  // cout << endl;
  int cnt = 0;
  for (int i = 1; i <= n; i ++ )
    if (dp[a[i]] == 1) cnt ++;
  cout << cnt << endl;
}
int main()
{
  int T; cin >> T;
  while (T -- )
  {
    work();
  }
  return 0;
}

C 要变强,不空喊,ak题目,继续向前。

题意:给定n个区间,我们可以从每个区间中选出一个数,将这些选出的数的平方加一起算个和,输出这些和的个数
看到这里,我们很明显的想到了这是一个分组背包问题,每组内只可以选择一个物品。按照分组背包的模板,我们要做的是第一维枚举组别,第二维枚举区间大小(100个数,每个数要平方,显然就是1e6大小的),第三位枚举背包内的物品。
f[i][j]表示前i个数能否组成j这个数的意义,可以用bool来存。但是,我们发现,时间一定会超限,这里我们可以用bitset来存数组

#include <bits/stdc++.h>
using namespace std;
int n;
bitset<1010> f[110];
int main(void)
{
  cin >> n;
  f[0][0] = 1;
  for (int i = 1; i <= n; i ++ )
  {
    int l, r; scanf("%d%d", &l, &r);
    for (int k = l; k <= r; k ++ )
      f[i] |= f[i - 1] << (k * k);
  }
  cout << f[n].count() << "\n";
  return 0;
}

D

E

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值