Codeforces Round #307 (Div. 2)

来源:互联网 发布:poe网络监控安装教程 编辑:程序博客网 时间:2024/05/19 05:01

唉最近状态越来越差。。。

A. GukiZ and Contest

给你n个人的分数然后输出排名。
一遍排序搞定。

#include <bits/stdc++.h>using namespace std;struct Node{    int val, pos;    bool operator < (const Node &n) const {        return val > n.val;    }};int n;Node arr[2005];map<int, int> vis;int ans[2005];int main() {    cin >> n;    for (int i = 1; i <= n; i++) {        cin >> arr[i].val;        arr[i].pos = i;    }    sort(arr + 1, arr + n + 1);    int tot = 0;    for (int i = 1; i <= n; i++) {              int t = arr[i].val;        if (vis[t]) {            ans[arr[i].pos] = vis[t];            tot++;        }        else {            vis[t] = ++tot;            ans[arr[i].pos] = tot;        }    }    for (int i = 1; i <= n; i++)        cout << ans[i] << " \n"[i == n];    return 0;}

B. ZgukistringZ

3个串a,b,c,可以将a任意重组,要求重组之后包含的无重叠部分的b串和c串的个数最多,问个数最多是多少。

计算a串26个字母分别出现了多少次,然后枚举b串的个数,计算最多能放多少c串。

#include <bits/stdc++.h>using namespace std;char a[100005], b[100005], c[100005];int cnta[30];int cntb[30];int cntc[30];int temp[30];int main() {    cin >> a >> b >> c;    int lena = strlen(a);    int lenb = strlen(b);    int lenc = strlen(c);    for (int i = 0; i < lena; i++) {        char c = a[i];        cnta[c - 'a']++;        temp[c - 'a']++;    }    for (int i = 0; i < lenb; i++) {        cntb[b[i] - 'a']++;    }    for (int i = 0; i < lenc; i++) {        cntc[c[i] - 'a']++;    }    int mx = 0;    int mxi = 0, mxj = 0;    for (int i = 0; i < lena; i++) {        int cc = 0x3f3f3f3f;        for (int j = 0; j < 26; j++) {            if (!cntc[j]) continue;            int t = cnta[j] / cntc[j];            cc = min(cc, t);        }        if (i + cc > mx) {            mxi = i;            mxj = cc;            mx = i + cc;        }        bool flag = false;        for (int k = 0; k < 26; k++) {            cnta[k] -= cntb[k];            if (cnta[k] < 0) {                flag = true;                break;            }        }        if (flag) break;    }    for (int i = 0; i < mxi; i++) {        printf("%s", b);    }    for (int i = 0; i < mxj; i++) {        printf("%s", c);    }    for (int i = 0; i < 26; i++) {        for (int j = 0; j < temp[i] - mxi * cntb[i] - mxj * cntc[i]; j++)            printf("%c", 'a' + i);    }    cout << endl;    return 0;}

C. GukiZ hates Boxes

n堆货物摆成一排,有m个人,所有人一开始在所有货物的左边。

每一分钟每个人可以有两种选择:

  1. 向右走一格。

  2. 把他当前所在位置的货物搬走一个。

问把所有货物都搬走最少需要多少分钟。

二分答案,判断能否在一定时间内搬完所有货物,过程如下:

对于每一个人,先让他走到最后一个有货物的位置,然后剩余的时间全部用来搬货物,先搬最后一堆,如果还有时间就搬倒数第二堆(依次类推)。注意他剩了多少时间一定能搬多少货物,因为在走到最后的过程中,可以随时花费一分钟用来搬货物。

#include <bits/stdc++.h>using namespace std;int n;long long m;long long arr[100005];long long temp[100005];bool solve(long long mid) {    for (int i = 1; i <= n; i++)        temp[i] = arr[i];    int pos = n;    long long tot = 0;    while (pos > 0) {        while (!temp[pos] && pos) pos--;        tot++;        long long tim = mid - pos;        if (tim <= 0 && temp[pos]) return false;        while (tim >= temp[pos] && pos) {            tim -= temp[pos];            temp[pos--] = 0;        }        temp[pos] -= tim;        if (tot > m) return false;    }    return tot <= m;}int main() {    cin >> n >> m;    for (int i = 1; i <= n; i++) {        cin >> arr[i];    }    long long l = 0, r = 2000000000000000;    while (l < r) {        long long mid = l + r >> 1;        if (solve(mid)) r = mid;        else l = mid + 1;    }    cout << l << endl;    return 0;}

D. GukiZ and Binary Operations

问有多少个长度为n的数组a,数组中的每个元素严格小于2l,满足(a1&a2)|(a2&a3)|...|(an1&an)=k?

输出方案数模m。

太神了我一点也不会。

我们枚举k的每一位,方案数就是每一位的方案数的乘积。

如果这一位是0,则说明数组一定没有连续两个元素是1。设dp[i]表示到第i位的方案数,很显然dp[i]=dp[i1]+dp[i2],用矩阵计算。

如果这一位是1,则说明数组中至少有一个两个连续的1,呃。。。不就是2ndp[n]么。

好了完了。

#include <bits/stdc++.h>using namespace std;long long n, k, l, m;struct matrix{    int n, m;    long long arr[2][2];    matrix(int a, int b) {        n = a, m = b;        memset(arr, 0, sizeof(arr));    }};matrix operator * (matrix a, matrix b) {    matrix c(a.n, b.m);    for (int i = 0; i < a.n; i++) {        for (int j = 0; j < b.m; j++) {            for (int p = 0; p < a.m; p++) {                long long t = a.arr[i][p] * b.arr[p][j] % m;                c.arr[i][j] += t;                c.arr[i][j] %= m;            }        }    }    return c;}matrix pow(matrix a, long long b) {    matrix c(2, 2);    c.arr[0][0] = c.arr[1][1] = 1;    while (b) {        if (b & 1) c = c * a;        a = a * a;        b >>= 1;    }    return c;}bool judge() {    long long t = k;    for (int i = 0; i < l; i++) t >>= 1;    return t == 0;}long long DP() {    matrix ans(1, 2);    ans.arr[0][0] = ans.arr[0][1] = 1;    matrix base(2, 2);    base.arr[0][1] = base.arr[1][0] = base.arr[1][1] = 1;    base = pow(base, n);    ans = ans * base;    return ans.arr[0][1];}long long power(long long a, long long b) {    long long ans = 1;    while (b) {        if (b & 1)            ans = ans * a % m;        a = a * a % m;        b >>= 1;    }    return ans;}int main() {    cin >> n >> k >> l >> m;    if (!judge()) {        cout << 0 << endl;        return 0;    }    long long ans = 1;    long long a = DP();    long long b = (power(2ll, n) - a + m) % m;    for (int i = 0; i < l; i++) {        if ((k >> i) & 1)            ans = ans * b % m;        else ans = ans * a % m;    }    cout << ans % m << endl;    return 0;}

E. GukiZ and GukiZiana

一个长度为n的序列,要求维护两种操作:

  1. 1 l r x. 把[l, r]中的所有数加上x。

  2. 2 y. 询问j - i的最大值使a[i] = a[j] = y。

分块。

把数组分成n块,每块n个数,然后对每一块排序。

对于操作1,如果[l, r]覆盖了某一块,则给这一块加上一个标记。

如果[l, r]覆盖了某一块的一部分则暴力加上x。

对于操作2,枚举每一块用lower_bound查找值。

第一次写分块,如何装作经常写的样子?写的不好见谅。

#include <bits/stdc++.h>#define pli pair<long long, int>#define mp(i, j) make_pair(i, j)using namespace std;const int MAXN = 500005;int n, q;long long arr[MAXN];int blocks;long long tag[MAXN];vector<pli > mi[770], mx[770];void rebuild(int id) {    mi[id].clear();    mx[id].clear();    for (int i = id * blocks; i < (id + 1) * blocks && i < n; i++) {        arr[i] += tag[id];        mi[id].push_back(mp(arr[i], i));        mx[id].push_back(mp(arr[i], -i));    }    sort(mi[id].begin(), mi[id].end());    sort(mx[id].begin(), mx[id].end());    tag[id] = 0;}int getmin(long long v) {    for (int i = 0; i < blocks; i++) {        long long t = v - tag[i];        vector<pli >::iterator it = lower_bound(mi[i].begin(), mi[i].end(), mp(t, 0));        if (it != mi[i].end() && (it -> first == t)) return it -> second;    }    return -1;}int getmax(long long v) {    for (int i = blocks - 1; i >= 0; i--) {        long long t = v - tag[i];        vector<pli >::iterator it = lower_bound(mx[i].begin(), mx[i].end(), mp(t, -10000000));        if (it != mx[i].end() && (it -> first == t)) return -it -> second;    }    return -1;}int main() {    cin >> n >> q;    blocks = sqrt(n) + 2;    for (int i = 0; i < n; i++)        cin >> arr[i];    for (int i = 0; i < blocks; i++)        rebuild(i);    int op, l, r;    long long v;    for (int i = 0; i < q; i++) {        cin >> op;        if (op == 1) {            cin >> l >> r >> v;            l--, r--;            if (l / blocks == r / blocks) {                for (int j = l; j <= r; j++)                    arr[j] += v;                rebuild(l / blocks);            } else {                int id = l / blocks + 1;                while (l / blocks != id) {                    arr[l++] += v;                }                rebuild(l / blocks - 1);                while (l + blocks < r) {                    tag[l / blocks] += v, l += blocks;                }                while (l <= r) arr[l++] += v;                rebuild(r / blocks);            }        } else {            cin >> v;            l = getmin(v);            r = getmax(v);            if (l < 0) cout << -1 << endl;            else cout << r - l << endl;        }    }    return 0;}
0 0