牛客练习赛59

传送门

A.小乔和小灰灰

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/3/13 19:00:59
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1000 + 5;

const string s = "XiaoQiao", t = "XiaoHuiHui";

string ss;

void run() {
    cin >> ss;
    int len = ss.length();
    int t1 = 0, t2 = 0;
    for(int i = 0; i < len; i++) {
        if(t1 < 8 && ss[i] == s[t1]) ++t1;
        if(t2 < 10 && ss[i] == t[t2]) ++t2;
    }
    if(t1 == 8 && t2 == 10) {
        cout << "Happy" << '\n';   
    } else cout << "emm" << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

B.牛能和小镇

排序后贪心计算即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/3/13 19:12:53
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A>
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
int n;
ll a[N];
 
void run() {
    cin >> n;
    for(int i = 1; i <= n; i++) {
        int x, y; cin >> x >> y;
        a[i] = 1ll * y * (x - y) * (x - y);  
    }
    sort(a + 1, a + n + 1);
    ll ans = 0;
    for(int i = 2; i <= n; i++) {
        ans += a[i] - a[i - 1];  
    }
    cout << ans << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

C.装备合成

题意:
牛牛有\({x}\)件材料\(a\)\({y}\)件材料\(b\),用\(2\)件材料\(a\)\(3\)件材料\(b\)可以合成一件装备,用\(4\)件材料\(a\)\(1\)件材料\(b\)也可以合成一件装备。牛牛想要最大化合成的装备的数量,于是牛牛找来了你帮忙。

思路:
显然最终答案具有单调性。
那么二分答案\(t\),假设最后用第一种方法合成了\(A\)件装备,那么第二种方法合成了\(B\)件装备,那么可以列出如下式子:

  • \(2A+4B\leq x,3A+B\leq y,A+B=t\).

最后可以解出\(A\)的范围。二分时\(check\)一下是否合法即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/3/13 19:21:23
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

ll a, b;
bool chk(ll t) {
    ll l = ceil(1.0 * (4 * t - a) / 2), r = floor(1.0 * (b - t) / 2);
    return l <= r && l <= t && r >= 0;
}

void run() {
    cin >> a >> b;
    int l = 0, r = INF, mid;
    while(l < r) {
        mid = (l + r) >> 1;
        if(chk(mid)) l = mid + 1;
        else r = mid;   
    }
    cout << l - 1 << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

D.取石子游戏

\(sg\)函数有规律,直接算就行。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/3/13 20:15:51
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

ll f[N];
int t;

void init() {
    ll Max = 4e18;
    f[1] = 1, f[2] = 3;
    for(int i = 3;; i++) {
        f[i] = f[i - 1] * 2;
        if(i % 2 == 0) ++f[i];
        if(f[i] >= Max) {
            t = i; break;   
        }
    }
}

void run() {
    ll n; cin >> n;
    int p = lower_bound(f + 1, f + t + 1, n) - f;
    if(p & 1) cout << "XiaoQiao" << '\n';
    else cout << "XiaoHuiHui" << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    init();
    int T; cin >> T;
    while(T--) run();
    return 0;
}

E.石子搬运

题意:
现有\(n\)堆石子,每堆有\(a_i\)个石头。现在可以将这\(n\)堆石子划分为\(m\)堆,每堆贡献为\(k_i^2\)
然后会发生\(q\)个事件,每个事件为\(x\ v\),即将第\(x\)堆石子个数变为\(v\)
对于每个事件,回答最小贡献。
\(1\leq n\leq m\leq 400,q\leq 400\)

思路:
对于每个事件我们单独计算,总体思路就是贪心,按照差值来进行贪心。
每次选择当前贡献能减少的最大值进行操作即可。
可以用一个优先队列来维护。shi
时间复杂度为\(O(qnlogn)\)
代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/3/13 23:06:41
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 400 + 5;

int n, m, q;
int a[N];

ll calc(int v, int k) {
    int r = v % k;
    int t = v / k;
    return 1ll * r * (t + 1) * (t + 1) + 1ll * (k - r) * t * t;
}

ll solve(int v, int k) {
    return calc(v, k) - calc(v, k + 1);
}

void run() {
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> a[i];
    cin >> q;
    while(q--) {
        int id, v; cin >> id >> v;
        a[id] = v;
        priority_queue <pair<ll, pii>> q;
        for(int i = 1; i <= n; i++) {
            q.push(pair<ll, pii>{solve(a[i], 1), MP(a[i], 1)});   
        }
        int k = m - n;
        while(k--) {
            pair <ll, pii> now = q.top(); q.pop();
            int val = now.se.fi, t = now.se.se + 1;
            q.push(pair<ll, pii>{solve(val, t), MP(val, t)});   
        }
        ll ans = 0;
        while(!q.empty()) {
            pair <ll, pii> now = q.top(); q.pop();
            int val = now.se.fi, t = now.se.se;
            ans += calc(val, t);
        }
        cout << ans << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

F.小松鼠吃松果

题意:
\(m\)个位置,有\(n\)个时刻在某些位置会生长一个价值为\(v_i\)的果子,每个果子只会存在一秒。
现在你可以任意选择一个点作为起点,每一秒只能向左或者向右移动一步。问最后能得到的最大价值是多少。

思路:
我们按照时间进行排序,如果我们要吃至少两个果子,那么要满足的条件为:

  • \(t_j-t_i\geq |p_i-p_j|\)

我们将绝对值打开,有:

  • \(p_i\geq p_j,t_j+p_j\geq t_i+p_i\);
  • \(p_i<p_j,t_j-p_j\geq t_i-p_i\)

那么令\(X_i=p_i+t_i,Y_i=t_i-p_i\)
那么我们按照\(X_i\)进行排序,问题可以转化为带权\(lis\)\(Y_i\)就是每个数的高度。我们要求最长不下降子序列的最大权值和。利用树状数组维护即可。
注意这里我们将问题转化为了二维问题。我们推出第二个式子的前提是按照时间排序,又可以发现只要满足第二个式子,第一个式子也自然满足了。如果没注意到这一点,就是一个三维问题,就像题解那样用树套树或者\(cdq\)分治这些来解决。
代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/3/14 10:23:00
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

int n, m;
int a[N], b[N];

struct node {
    int id, h, v;
    bool operator < (const node &A) const {
        if(id != A.id) return id < A.id;
        return h < A.h;
    }
}info[N];

struct BIT {
    ll c[N];
    int lowbit(int x) {return x & (-x);}
    void upd(int x, ll v) {
        for(; x < N; x += lowbit(x)) c[x] = max(c[x], v);
    }   
    ll query(int x) {
        ll res = 0;
        for(; x; x -= lowbit(x)) res = max(res, c[x]);
        return res;   
    }
}bit;

void run() {
    cin >> n >> m;
    for(int i = 1; i <= m; i++) cin >> a[i];
    for(int i = 1; i <= m; i++) cin >> b[i];
    for(int i = 1; i <= n; i++) {
        int t, p, c; cin >> t >> p >> c;
        int x = a[p], y = b[p] + t;
        info[i] = node{y - x, x + y, c};
    }
    sort(info + 1, info + n + 1);
    vector <int> v;
    for(int i = 1; i <= n; i++) v.push_back(info[i].h);
    sort(all(v));
    v.erase(unique(all(v)), v.end());
    for(int i = 1; i <= n; i++) {
        int h = lower_bound(all(v), info[i].h) - v.begin() + 1;
        bit.upd(h, bit.query(h) + info[i].v);
    }
    ll ans = bit.query(n);
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}
posted @ 2020-03-16 11:16  heyuhhh  阅读(311)  评论(0编辑  收藏  举报