zoukankan      html  css  js  c++  java
  • Codeforces Looksery Cup 2015

    在学考复习的时候偷偷打了这场cf,今天才有时间把题目都订正,囧

    B

    题目大意:n个人,每个人向一些人发邮件(都会给自己发),然后构造一个确定某些人发邮件的方案,使得每个人收到的邮件 $ eq a[i]$

    题解:因为每个人都会给自己发,所以当某人$= a[i]$时就把他自己选上

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 #define rep(i, l, r) for (int i = l; i <= r; i++)
     8 #define drep(i, r, l) for (int i = r; i >= l; i--)
     9 typedef long long ll;
    10 const int N = 108;
    11 int n, a[N], d[N], ans[N];
    12 char Map[N][N];
    13 int main()
    14 {
    15 #ifndef ONLINE_JUDGE
    16     freopen("input.txt","r",stdin);
    17     //freopen("output.txt","w",stdout);
    18 #endif
    19     scanf("%d", &n);
    20     rep(i, 1, n) scanf("%s", Map[i] + 1);
    21     rep(i, 1, n) scanf("%d", &a[i]);
    22     bool flag = false;
    23     while (!flag)
    24     {
    25         flag = 1;
    26         rep(i, 1, n) if (a[i] == d[i]) 
    27         {
    28             flag = 0;
    29             ans[++ans[0]] = i;
    30             rep(j, 1, n) if (Map[i][j] == '1') d[j]++;
    31             break;
    32         }
    33     }
    34     sort(ans + 1, ans + ans[0] + 1);
    35     printf("%d
    ", ans[0]);
    36     rep(i, 1, ans[0]) printf("%d ", ans[i]); printf("
    ");
    37 #ifndef ONLINE_JUDGE
    38     fclose(stdin); fclose(stdout);
    39 #endif
    40     return 0;
    41 }
    B

    C

    题目大意:S和D玩游戏,S先手。一共n堆石头,每次可以拿走一堆,剩下k堆就结束。S希望最后留下的石头总数是奇数,D希望是偶数

    题解:特判n = k的情况,然后注意到最后一次操作时,如果奇偶石头都有,那么操作的人就获胜了。根据这个来分类讨论

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 #define rep(i, l, r) for (int i = l; i <= r; i++)
     8 #define drep(i, r, l) for (int i = r; i >= l; i--)
     9 typedef long long ll;
    10 const int N = 2e5 + 8;
    11 int n, k, a[N], c[2];
    12 void out(int x)
    13 //x:最后的奇偶性 
    14 {
    15     printf("%s
    ", x == 1 ? "Stannis " : "Daenerys");
    16 }
    17 void solve()
    18 //先手奇数,后手偶数 
    19 {
    20     if (!c[1]) {out(0); return;}
    21     if (!c[0]) {out(k & 1); return;}
    22     if ((n - k) & 1)
    23     //先手控制最后一步 
    24     {
    25         int x = (n - k) / 2 + 1, y = n - k - x; x--; 
    26         if (y >= c[1]) out(0);
    27         else if (y < c[0]) out(1);
    28         else out(k & 1);
    29     }
    30     else
    31     //后手控制最后一步 
    32     {
    33         int x = (n - k) / 2, y = n - k - x; y--;
    34         if (x >= c[0]) out(k & 1);
    35         else out(0);
    36     }
    37 }
    38 int main()
    39 {
    40 #ifndef ONLINE_JUDGE
    41     freopen("input.txt", "r", stdin);
    42     //freopen("output.txt", "w", stdout);
    43 #endif
    44     scanf("%d%d", &n, &k);
    45     rep(i, 1, n) scanf("%d", &a[i]), c[(a[i] & 1) ? 1 : 0]++;
    46     if (n == k)
    47     {
    48         out(c[1] & 1);
    49         return 0;
    50     }
    51     solve();
    52 #ifndef ONLINE_JUDGE
    53     fclose(stdin); fclose(stdout);
    54 #endif
    55     return 0;
    56 }
    C

    D

    题目大意:给一个$n imes m$的矩阵,矩阵有黑白格子,选择最少的前缀矩阵,使得可以计算所有黑格子上的权值和-白格子权值和

    题解:倒着扫一遍,贪心选择,使得白格子是-1,黑格子是1

    D

    E

    不会

    F

    题目大意: 给定一个序列,求有多少个长度大于等于2的区间满足区间和$-$区间最大值是$k$的倍数

    题解: 递归解决。假设现在处理区间$[l, r]$,先找到最大值,然后只遍历短的那一边,计算当前的和,然后算出另一边应该是多少,则问题变成了求一段区间等于某个值的有多少个,可以用主席树解决

    时间复杂度$O(n{log^2}n)$

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define rep(i, l, r) for (int i = l; i <= r; i++)
    #define drep(i, r, l) for (int i = r; i >= l; i--)
    typedef long long ll;
    const int N = 3e5 + 8, Log = 23;
    int n, k, tot, a[N], sum[N], st[Log][N], son[N], rt[N];
    ll ans;
    struct Node
    {
        int l, r, s;
    }t[N * Log];
    void Insert(int x, int o, int l, int r, int p, int d)
    {
        t[x].s = t[o].s + d;
        if (l == r) return;
        int mid = l + r >> 1;
        if (p <= mid) t[x].r = t[o].r, Insert(t[x].l = ++tot, t[o].l, l, mid, p, d);
        else t[x].l = t[o].l, Insert(t[x].r = ++tot, t[o].r, mid + 1, r, p, d);
    }
    int query(int x, int o, int l, int r, int p)
    {
        if (l == r) return t[x].s - t[o].s;
        int mid = l + r >> 1;
        if (p <= mid) return query(t[x].l, t[o].l, l, mid, p);
        return query(t[x].r, t[o].r, mid + 1, r, p);
    }
    void init()
    {
        rep(i, 1, n) 
        {
            son[i] = son[i - 1];
            if ((1 << son[i] + 1) == i) son[i]++; 
        }
        rep(i, 1, n) st[0][i] = i;
        rep(i, 1, son[n])
            rep(j, 1, n)
            if (j + (1 << i) - 1 <= n)
            {
                int x = st[i - 1][j], y = st[i - 1][j + (1 << i - 1)];
                st[i][j] = a[x] > a[y] ? x : y;
            }
        rep(i, 0, n)
        {
            if (i) sum[i] = (sum[i - 1] + a[i]) % k;
            Insert(rt[i + 1] = ++tot, rt[i], 0, k - 1, sum[i], 1);
        }
    }
    int stquery(int l, int r)
    {
        int k = son[r - l + 1];
        int x = st[k][l], y = st[k][r - (1 << k) + 1];
        return a[x] > a[y] ? x : y;
    }
    void solve(int l, int r)
    {
        if (l == r) {ans++; return;}
        if (l > r) return;
        int p = stquery(l, r);
        //printf("_______%d %d %d
    ", l, r, p);
        ll tmp = ans;
        if (p - l + 1 <= r - p + 1)
        {
            int s = 0;
            drep(i, p, l)
            {
                if (i != p) s = (s + a[i]) % k;
                int x = (-s + k + sum[p]) % k;
                ans += query(rt[r + 1], rt[p], 0, k - 1, x);
            }
        }
        else
        {
            int s = 0;
            rep(i, p, r)
            {
                if (i != p) s = (s + a[i]) % k;
                int x = (sum[p - 1] + k - (-s + k)) % k;
                //printf("%d %d %d
    ", x, p - 1, max(l - 2, 0));
                ans += query(rt[p], rt[l - 1], 0, k - 1, x); 
            }
        }
        //printf("%I64d
    ", ans - tmp);
        solve(l, p - 1); solve(p + 1, r);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        //freopen("output.txt","w",stdout);
    #endif
        scanf("%d%d", &n, &k);
        rep(i, 1, n) scanf("%d", &a[i]);
        init();
        solve(1, n);
        ans -= n;
        printf("%I64d
    ", ans);
    #ifndef ONLINE_JUDGE
        fclose(stdin); fclose(stdout);
    #endif
        return 0;
    }
    F

    G

    题目大意:给一个序列,每次可以交换$a[i]$和$a[i + 1]$,但是交换前$a[i]$要给一块钱给$a[i + 1]$,如果$a[i]$为$0$就不能交换,求最后的序列,使得序列不降

    题解: 如果把n个数放在楼梯上(也就是$a[i] + i$),那么交换两个数就相当于把楼梯这两级包括上面的一起交换。显然要把高的往后面放。所以直接按照$a[i] + i$排序,然后再复原,检验答案

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 #define rep(i, l, r) for (int i = l; i <= r; i++)
     8 #define drep(i, r, l) for (int i = r; i >= l; i--)
     9 typedef long long ll;
    10 const int N = 200008;
    11 int n, a[N];
    12 int main()
    13 {
    14 #ifndef ONLINE_JUDGE
    15     freopen("input.txt","r",stdin);
    16     //freopen("output.txt","w",stdout);
    17 #endif
    18     scanf("%d", &n);
    19     rep(i, 1, n) scanf("%d", &a[i]), a[i] += i;
    20     sort(a + 1, a + n + 1);
    21     rep(i, 1, n) a[i] -= i;
    22     rep(i, 1, n - 1) if (a[i] > a[i + 1]) 
    23     {
    24         printf(":(
    "); return 0;
    25     }
    26     rep(i, 1, n) printf("%d ", a[i]); printf("
    ");
    27 #ifndef ONLINE_JUDGE
    28     fclose(stdin); fclose(stdout);
    29 #endif
    30     return 0;
    31 }
    G

    H

    题目大意:给出矩阵$A$,构造权值为0矩阵$B$,使得$A - B$每一项绝对值的最大值最小

    题解:二分答案,然后A的四个值变成了四个范围,然后求出$ac$和$bd$的范围,判断是否相交。注意因为有负数所以最小值乘最小值不一定就是最小值

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 #define rep(i, l, r) for (int i = l; i <= r; i++)
     8 #define drep(i, r, l) for (int i = r; i >= l; i--)
     9 typedef long long ll;
    10 typedef double real;
    11 #define double long double
    12 const double eps = 1e-10;
    13 int a, b, c, d;
    14 double ans;
    15 double getmin(double x, double y, double z)
    16 {
    17     double v1 = (x - z) * (y - z);
    18     double v2 = (x + z) * (y - z);
    19     double v3 = (x + z) * (y + z);
    20     double v4 = (x - z) * (y + z);
    21     return min(v1, min(v2, min(v3, v4)));
    22 }
    23 double getmax(double x, double y, double z)
    24 {
    25     double v1 = (x - z) * (y - z);
    26     double v2 = (x + z) * (y - z);
    27     double v3 = (x + z) * (y + z);
    28     double v4 = (x - z) * (y + z);
    29     return max(v1, max(v2, max(v3, v4)));
    30 }
    31 int main()
    32 {
    33 #ifndef ONLINE_JUDGE
    34     freopen("input.txt","r",stdin);
    35     //freopen("output.txt","w",stdout);
    36 #endif
    37     scanf("%d%d", &a, &b);
    38     scanf("%d%d", &c, &d);
    39     double l = 0, r = 1e9;
    40     while (fabs(r - l) > eps)
    41     {
    42         double mid = (l + r) / 2.0;
    43         double l1 = getmin(a, d, mid);
    44         double r1 = getmax(a, d, mid);
    45         double l2 = getmin(b, c, mid);
    46         double r2 = getmax(b, c, mid);
    47         if (r2 < l1 || l2 > r1) l = mid;
    48         else r = mid;
    49     }
    50     printf("%.10lf
    ", (real)l);
    51 #ifndef ONLINE_JUDGE
    52     fclose(stdin); fclose(stdout);
    53 #endif
    54     return 0;
    55 }
    H
  • 相关阅读:
    HDU 1203 【01背包/小数/概率DP】
    HDU 2955 【01背包/小数/概率DP】
    2018 计蒜之道 初赛 第三场
    判断一个多边形是顺时针还是逆时针的方法
    牛客网练习赛18 A 【数论/整数划分得到乘积最大/快速乘】
    Codeforces Round #311 (Div. 2)
    暑期训练狂刷系列——Hdu 3506 Largest Rectangle in a Histogram (单调栈)
    暑期训练狂刷系列——poj 3468 A Simple Problem with Integers (线段树+区间更新)
    暑期训练狂刷系列——Foj 1894 志愿者选拔 (单调队列)
    暑期训练狂刷系列——poj 3264 Balanced Lineup(线段树)
  • 原文地址:https://www.cnblogs.com/Dyzerjet/p/4576744.html
Copyright © 2011-2022 走看看