补题:牛客2019跨年AK场

比赛入口


新的一年,又是改不完的bug和补不完的题,QAQ

B 【客】希望

做法:题意是在某个范围中使[l,r]区间数字变为0需要c[i]点能量,要问在k点能量的限制下,总和最大为多少。
大佬说用线段树加01背包,然而后来还是想错了,开始我在v数组上建了一棵线段树,后来发现在做01背包的时候会有重复,其实正解是在w数组上建线段树,后面再对两个数组进行01背包。
还有一个小技巧,最后要减的是最小的权值,所以取负号取最大,输出答案时dp[k]变号即可。

代码

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int N = 1e5+5;
LL T[4*N];
void update(int rt, int l, int r, int L, int R, LL x) {
  if(l > R || L > r) return ;
  if(L <= l && R >= r) {
    T[rt] = min(T[rt], x);
    return ;
  }
  int mid = l + r >> 1;
  update(lson, L, R, x);
  update(rson, L, R, x);
}
LL query(int rt, int l, int r, int pos) {
  if(l == r) return T[rt];
  int mid = l + r >> 1;
  if(pos <= mid) return min(T[rt], query(lson, pos));
  else return min(T[rt], query(rson, pos));
}
LL v[N];
LL dp[510], sum;
int main() {
  memset(T, 0x3f, sizeof T);
  LL n, k, m;
  scanf("%lld%lld%lld", &n, &k, &m);
  for(int i = 1; i <= n; ++i) {
    scanf("%lld", &v[i]);
    sum += v[i];
  }
  int l, r;
  LL c;
  for(int i = 1; i <= m; ++i) {
    scanf("%d%d%lld", &l, &r, &c);
    update(1, 1, n, l, r, c);
  }
  LL w;
  for(int i = 1; i <= n; ++i) {
    if(v[i] >= 0) continue;
    w = query(1, 1, n, i);
    v[i] = -v[i];
    for(int j = k; j >= w; --j) {
      dp[j] = max(dp[j], dp[j-w] + v[i]);
    }
  }
  printf("%lld\n", sum + dp[k]);
  return 0;
}

D 【祝】Rinne Loves Study

做法:二维数组用一维数组表示行和列,后面再输出行和列出现时间之间的最大值。

代码

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int N = 1e5+5;
int row[N], col[N];  //表示二维数组的行和列数组
int main() {
  int n, m, t;
  read(n); read(m); read(t);
  int pos, num;
  for(int i = 1; i <= t; ++i) {
    read(pos); read(num);
    if(pos == 1) row[num] = i;
    else col[num] = i;
  }
  for(int i = 1; i <= n; ++i) {
    for(int j = 1; j <= m; ++j) {
      printf("%d ", max(row[i], col[j]));
    }
    puts("");
  }
  return 0;
}

F 【家】神秘钥匙

做法:用找规律的方法
2 :
(1),(2) --> 12种
(1,2) --> 2种
3:
(1),(2),(3) --> 1
3种
(1,2),(1,3),(2,3) --> 2*2种
(1,2,3) --> 3种
易得
C n 1 + 2 C n 2 + 3 C n 3 + . . . + n C n n = n 2 n 1 C_n^1 + 2 * C_n^2 + 3 * C_n^3 + ... + n * C_n^n = n * 2 ^{n-1}
代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL Mod = 1e9+7;
LL ksm(LL a, LL n) {
  LL sum = 1;
  while(n) {
    if(n & 1) sum = sum * a % Mod;
    a = a * a % Mod;
    n >>= 1;
  }
  return sum;
}
int main () {
    LL n;
    cin >> n;
    cout << n * ksm(2, n-1) % Mod << endl;
    return 0;
}

G 【跨】小sun的假期

做法:对端点进行贪心判断,欸,最后还是找不到bug看了大佬的代码…

代码

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int N = 1e5+5;
struct xx {
  int l, r;
  bool operator < (const xx &c) const {
    if(l != c.l) return l < c.l;
    return r < c.r;
  }
}ap[N];
int main() {
  int n, m;
  read(n); read(m);
  for(int i = 1; i <= m; ++i) {
    read(ap[i].l); read(ap[i].r);
  }
  sort(ap+1, ap+m+1);
  int ans = 0, L = 0, R = 0;
  for(int i = 1; i <= m; ++i) {
    if(R > ap[i].l) R = max(R, ap[i].r);
    else if(R < ap[i].l) {
      ans = max(ans, ap[i].l - L);
      L = R + 1; R = ap[i].r;
    }
  }
  printf("%d\n", max(ans, n-R));
  return 0;
}

发布了28 篇原创文章 · 获赞 14 · 访问量 2961

猜你喜欢

转载自blog.csdn.net/qq_43408978/article/details/103791375