zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 41 A B C D E

    A. Tetris

    题意

    俄罗斯方块,问能得多少分。

    思路

    即求最小值

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    using namespace std;
    typedef long long LL;
    #define maxn 1010
    int cnt[maxn];
    int main() {
        int n,m,x;
        scanf("%d%d", &n, &m);
        F(i, 0, m) {
            scanf("%d", &x);
            ++cnt[x];
        }
        int ans = m;
        F2(i ,1, n) ans = min(ans, cnt[i]);
        printf("%d
    ", ans);
        return 0;
    }
    
    

    B. Lecture Sleep

    题意

    一节课共(n)秒,(t_i=1)当且仅当小明在第(i)秒会打盹,小明能学习到(a_i)个知识点当且仅当他在第(i)秒不打盹。

    现在有一种魔法能让小明连续(k)秒不打盹,但只能使用一次,要求最大化小明能学习到的知识点个数。

    思路

    计算两个前缀和,枚举使用魔法的开始时刻借助前缀和(O(1))计算对应的收益。

    时间复杂度:(O(n)).

    // 菜菜我被条件表达式实力坑了一波,切记切记它的优先级相当低,低于算术运算,低于位运算,低于逻辑运算,切记切记加括号加括号。

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 100010
    using namespace std;
    typedef long long LL;
    LL a[maxn], pre[maxn], pre2[maxn];
    int main() {
        int n, k;
        scanf("%d%d", &n, &k);
        F2(i, 1, n) {
            scanf("%I64d", &a[i]);
            pre[i] = pre[i-1] + a[i];
        }
        F2(i, 1, n) {
            int t = 0;
            scanf("%d", &t);
            pre2[i] = pre2[i-1] + (t?a[i]:0);
        }
        LL ans = 0;
        F2(i, 1, n-k+1) {
            ans = max(ans, pre2[i-1]-pre2[0]+pre2[n]-pre2[i+k-1]+pre[i+k-1]-pre[i-1]);
        }
        printf("%I64d
    ", ans);
        return 0;
    }
    
    
    

    C. Chessboard

    题意

    一个合法的棋盘中,相邻格子的颜色(黑、白)不同。

    现在一个(2n imes2n)的棋盘碎成了四块(n imes n)的棋盘,并且有一些格子的颜色发生了变化。

    要求将它拼起来,并且修改最少格子的颜色,得到一个合法的棋盘。

    思路

    将棋盘拼起来有(4!=24)种方案,对每种方案去计算一个数目,最后取最小值。

    注意到,合法的棋盘只可能有两种,且由左上角的格子唯一确定。

    所以对每种方案去计算数目的只需要与这两种棋盘对比,取最小。

    时间复杂度:(O(48n^2))

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 110
    #define maxm 210
    using namespace std;
    typedef long long LL;
    char s[maxn];
    int n;
    bool b[maxm][maxm], st1[maxm][maxm], st2[maxm][maxm];
    struct board {
        int c[maxn][maxn];
    }a[4];
    void concat(int x1,int x2,int x3,int x4) {
        F(i, 0, n) F(j, 0, n) b[i][j] = a[x1].c[i][j];
        F(i, n, n<<1) F(j,0,n) b[i][j] = a[x2].c[i-n][j];
        F(i, 0, n) F(j, n, n<<1) b[i][j] = a[x3].c[i][j-n];
        F(i, n, n<<1) F(j, n, n<<1) b[i][j] = a[x4].c[i-n][j-n];
        int m = n<<1;
    }
    void init() {
        int m=n<<1;
        F(i, 0, m) F(j, 0, m) st1[i][j] = (i+j)&1, st2[i][j] = !st1[i][j];
    }
    int work() {
        int m = n<<1, ret1=0, ret2=0;
        F(i, 0, m) F(j, 0, m) ret1 += st1[i][j]!=b[i][j];
        F(i, 0, m) F(j, 0, m) ret2 += st2[i][j]!=b[i][j];
        return min(ret1, ret2);
    }
    int main() {
        scanf("%d", &n);
        init();
        F(i, 0, 4) {
            F(j, 0, n) {
                scanf("%s", s);
                F(k, 0, n) a[i].c[j][k] = s[k]=='1'?1:0;
            }
        }
        int ans = n*n*4;
        F(x1,0,4) {
            F(x2,0,4) {
                if (x2==x1) continue;
                F(x3,0,4) {
                    if (x3==x2||x3==x1) continue;
                    F(x4,0,4) {
                        if (x4==x1||x4==x2||x4==x3) continue;
                        concat(x1,x2,x3,x4);
                        ans = min(ans, work());
                    }
                }
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    
    

    D. Pair Of Lines

    题意

    平面上一些点,问是否能画出两条直线,使得穿过平面上所有点。

    思路

    若点数(leq 3),显然可行。

    否则,取前三个点,必有(1,2)共线或是(1,3)共线或是(2,3)共线(若2,3不共线,则必有至少一点与1共线),对这三种情况(check)其他点是否满足要求,若均不满足,则为(NO).

    (check)时将共线的所有点扔掉,再(check)剩下的所有点是否共线。

    共线用叉积计算。

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 100010
    using namespace std;
    typedef long long LL;
    struct Point {
        LL x, y;
        Point operator - (const Point& p) const { return {x-p.x, y-p.y}; }
    }p[maxn];
    int n;
    inline bool cross(Point a, Point b) { return a.y*b.x==a.x*b.y; }
    inline bool collinear(int x, int y, int z) { return cross(p[x]-p[y], p[x]-p[z]); }
    bool ok(int x, int y) {
        vector<int> v;
        F(i, 0, n) {
            if (!collinear(x,y,i)) v.push_back(i);
        }
        if (v.size()<=2) return true;
        x=v[0], y=v[1];
        for (auto i : v) {
            if (!collinear(x,y,i)) return false;
        }
        return true;
    }
    int main() {
        scanf("%d", &n);
        F(i, 0, n) scanf("%I64d%I64d", &p[i].x, &p[i].y);
        if (n<=4) puts("YES");
        else if (ok(0, 1)) puts("YES");
        else if (ok(0, 2)) puts("YES");
        else if (ok(1, 2)) puts("YES");
        else puts("NO");
        return 0;
    }
    
    
    

    E. Tufurama

    题意

    给定一个序列,问有多少对(i,j)满足(a[i]geq j,a[j]geq i).

    思路

    考虑对于某个(i)去找有多少个(j)满足条件,首先,寻找的下标范围为(jin[1,a[i]]),此外需要满足的条件为(a[j]geq i).

    下标范围的条件好处理,第二个条件怎么办呢?要是每次计算的时候范围内的点都是满足第二个条件的该多好啊!

    所以,每次算完之后将不满足条件的扔掉就行了。因为(i)是递增的,所以可以放心大胆扔。

    从小到大,对于每个(i),统计有多少个下标在([1,a[i]])的范围内,然后扔掉值为(i)的所有下标,这样每次算的时候统计到的都是满足第二个条件的下标了。

    // 其实是种很常见的想法...。
    // 翻了一下很容易就找到了hdu 3887...。

    (vector[x])记录值为(x)的所有下标,用树状数组维护下标的个数。

    注意最后去掉多算的部分,一部分是和本身,另一部分因为该关系是等价关系所以会算两次。

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 200010
    using namespace std;
    typedef long long LL;
    int c[maxn], a[maxn], n;
    vector<int> v[maxn];
    inline int lowbit(int x) { return x & (-x); }
    inline void add(int x, int d) { while (x<=n) c[x]+=d, x+=lowbit(x); }
    inline LL query(int x) { LL ret=0; while (x) ret+=c[x], x-=lowbit(x); return ret; }
    int main() {
        scanf("%d", &n);
        F2(i, 1, n) {
            scanf("%d", &a[i]);
            if (a[i]<=n) v[a[i]].push_back(i);
            add(i, 1);
        }
        LL ans = 0;
        F2(i, 1, n) {
            ans += query(min(a[i], n));
            for (auto x : v[i]) add(x, -1);
        }
        F2(i, 1, n) if (a[i]>=i) --ans;
        printf("%I64d
    ", ans>>1);
        return 0;
    }
    
    
  • 相关阅读:
    JavaScript常用正則表達式
    详尽解析window.event对象
    DWR的类却无法在js里用
    javascript控制小数点精度
    49. Group Anagrams
    48. Rotate Image
    64. Minimum Path Sum
    63. Unique Paths II
    62. Unique Paths
    53. Maximum Subarray
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/8724918.html
Copyright © 2011-2022 走看看