zoukankan      html  css  js  c++  java
  • 4.21小练

    Mutual Training for Wannafly Union #3 & 4

    我不知道我以后还记不记得补题。。。我只能尽量当天睡觉前能补多少就补多少,时间总是不够用,脑子更不够用orz

    题目链接:https://vjudge.net/contest/159576#overview

    A - Dungeon Trap     [ UVALive – 7220 ]  【最短路bfs】

    //yy:练题时都没看这题,看题目就以为很难。。。晚上补 的时候发现居然是最短路,奥妙重重。。。

    题意:0表示障碍,要将非0数转化成0(会花费这个数的值)使得A和B不连通(该题连通为四连通),问最大花费多少。

    看着题解做的,枚举最后一个放置障碍的点,则ans=max(ans,sum-(从A到这个点的距离+从B到这个点的距离-2*这个点的权值));

    //补题:AC  by  lyy:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<limits.h>
    #define CLR(a,b) memset((a),(b),sizeof((a)))
    using namespace std;
    typedef long long ll;
    const int N = 105;
    const int inf = 0x3f3f3f3f;
    int n, m;
    int sum;
    int dx[] = {1,0,-1,0};
    int dy[] = {0,1,0,-1};
    char s[N][N];
    int d[N][N][2];
    int ans;
    int ax, ay, bx, by;
    bool check(int x, int y) {
        if(x < 0 || x >= n || y < 0 || y >= m)
            return false;
        if(s[x][y] == '0')
            return false;
        return true;
    }
    struct node {
        int x, y;
    };
    void bfs(int x, int y, int id) {
        queue<node> q;
        d[x][y][id] = 0;
        q.push(node{x, y});
        while(!q.empty()) {
            node t = q.front(); q.pop();
            for(int i = 0; i < 4; ++i) {
                int xx = t.x + dx[i];
                int yy = t.y + dy[i];
                int w = s[xx][yy]-'0';
                if(check(xx, yy)) {
                    if(d[xx][yy][id] > d[t.x][t.y][id] + w) {
                        d[xx][yy][id] = d[t.x][t.y][id] + w;
                        q.push(node{xx, yy});
                    }
                }
            }
        }
    }
    int main(){
        int t;
        int i, j, k;
        scanf("%d",&t);
        for(k = 1; k <= t; ++k) {
            CLR(d, inf);
            scanf("%d%d", &n, &m);
            sum = 0;
            for(i = 0; i < n; ++i) {
                scanf("%s", s[i]);
                for(j = 0 ; j < m; ++j) {
                    if(s[i][j] == 'A') {
                        ax = i; ay = j;
                    }
                    else if(s[i][j] == 'B') {
                        bx = i; by = j;
                    }
                    else {
                        sum += s[i][j] - '0';
                    }
                }
            }
            bfs(ax, ay, 0);
            bfs(bx, by, 1);
            ans = 0;
            for(i = 0; i < n; ++i) {
                for(j = 0; j < m; ++j) {
                    if(s[i][j] >= '1' && s[i][j] <= '9') {
                        if(d[i][j][0] != inf && d[i][j][1] != inf) {
                            int c = s[i][j] - '0';
                            ans = max(ans, sum-d[i][j][0]-d[i][j][1]+2*c);
                        ]
                    }
                }
            }
            printf("Case #%d: %d
    ", k, ans);
        }
        return 0;
    }

    B - Pigeonhole Tower   [ SPOJ – PHT ] 【二分】

    题意:求用n根木棒能搭出多少层

    第一层3根,第二层5,第三层7.。。。2*n+1.。。。。。。二分数量

    //AC  by  lwq:

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    long long int q[1000000]; 
    int main()
    {
        int T;
        scanf("%d",&T);
        q[1]=3;
        int t=0;
        for(int i=2;i<=1000000;i++)
        {
            q[i]=q[i-1]+2*i+1;
        }
        while(T--)
        {
            t++;
            long long int n;
            scanf("%lld",&n);
            long long int L=1;
            long long int R=1000000;
            long long int MID=(L+R)/2;
            while(L+1<R)
            {
                if(n>=q[MID])
                {
                    L=MID;
                }
                else
                R=MID;
                
                MID=(L+R)/2;
            }
            if(n<3)
            MID=0;
            printf("Case %d: %lld
    ",t,MID);
        //    printf("%")
        }
        return 0;
    }

    C - Interesting Numbers  [ SPOJ – INUM ]  【二分】

    题意:求分别有几对数满足差值绝对值最大和最小。

    //AC  by  kn:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <climits>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 100;
    ll a[maxn];
    
    int main()
    {
        int n;
        cin >> n;
        for(int i = 0; i < n; ++i) {
            cin >> a[i];
        }
        ll mi = LONG_LONG_MAX;
        ll ma = LONG_LONG_MIN;
        sort(a, a + n);
        for(int i = 1; i < n; ++i) {
            mi = min(mi, a[i] - a[i - 1]);
        }
        ma = a[n - 1] - a[0];
        ll ans_mi = 0;
        ll ans_ma = 0;
        for(int i = 0; i < n; ++i) {
            ans_mi += (upper_bound(a + i + 1, a + n, a[i] + mi) - lower_bound(a + i + 1, a + n, a[i] + mi));
            ans_ma += (upper_bound(a + i + 1, a + n, a[i] + ma) - lower_bound(a + i + 1, a + n, a[i] + ma));
        }
        //cout << mi << " " << ma << endl;
        cout << ans_mi << " " << ans_ma << endl;
        return 0;
    }
    
    /*
    5
    0 0 2 0 0
    */

    D – SubXor   [SPOJ – SUBXOR]

    //yy:讨论了一会儿,我猜要用前缀树什么的,要不然超时,,然后大家都不会数据结构,然后就没有然后了orz,改天再补。。。

    E – Guards   [UVALive – 5813]

    //yy:就看懂了题意,没想出思路orz,很好玩,看题目发现构成一个矩形时就是一个集合,其他又是一个集合,然后想搜索,不会,也想不出怎么安排棋子;想了找规律,感觉也找不到;想了图论,也没想出什么,毕竟图论我感觉自己连基本概念都很多不知道;想了DP然后就不敢再想了。。。。放弃orz,改天补。。。

    F - Extremely Lagged Fibonacci   [SPOJ – EXLAGFIB]

    //yy:感觉太数学,再次放弃,害怕orz

    G - Smile House   [CodeForces – 147B]

    //yy:我看完这题突然想到floyd,dp之类的,但是不知道具体怎么处理,又放弃了orz,改天再补

    H - Renting Bikes   [CodeForces – 363D]  【贪心,二分】

    题意:已知每辆车的价格和人有的钱数和共享资金,每人最多买一辆车,问最多能买多少车以及私人花费的最多钱数。

    题解:二分买车的数量,用最有钱的mid个人买最便宜的mid辆车。

    //yy:二分折腾了好久orz结果最后细节没处理好一直WA,,二分求和时忘记改long long了。。

    补题:AC  by  lyy:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<limits.h>
    #define CLR(a,b) memset((a),(b),sizeof((a)))
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5;
    int n, m, k;
    int a[N], b[N];
    bool cmp(int x, int y) { return x > y; }
    int main(){
        int i, j;
        scanf("%d%d%d", &n, &m, &k);
        for(i = 0; i < n; ++i) scanf("%d", &a[i]);//人有的钱
        for(i = 0; i < m; ++i) scanf("%d", &b[i]);//车的价格
        sort(a, a+n, cmp);
        sort(b, b+m);
        int l = 0, r = min(n, m);
        while(l < r) {//二分买车的数量
            int mid = (l + r + 1) >> 1;
            ll s = 0;
            for(int i = 0; i < mid; ++i) {
                if(a[i] < b[mid-1-i]) {
                    s += b[mid-1-i] - a[i];
                }
            }
            if(s > k) r = mid-1;
            else l = mid;
        }
        printf("%d ", r);
        ll s = 0;
        for(i = 0; i < r; ++i) {
            s += b[i];
        }
        s -= k;
        if(s < 0) s = 0;
        printf("%lld
    ", s);
        return 0;
    }

    I - Greg's Workout  [CodeForces – 255A]  【水题】

    //AC  by  lyy:我觉得自己好水啊、、、

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<limits.h>
    #define CLR(a,b) memset((a),(b),sizeof((a)))
    using namespace std;
    typedef long long ll;
    const int N = 1e5;
    const int mod = 1e9+7;
    int a[30];
    int main() {
        int n;
        scanf("%d", &n);
        int i, j;
        int x = 0, y = 0, z = 0;
        for(i = 0; i < n; ++i) {
            scanf("%d", &a[i]);
            if(i % 3 == 0) {x += a[i];}
            else if(i % 3 == 1) {y+=a[i];}
            else z+=a[i];
        }
        if(x >= y ) {
            printf("%s
    ", x > z ? "chest" : "back");
        }
        else printf("%s
    ", y > z ?  "biceps" : "back");
        return 0;
    }

    J - MUH and Cube Walls  [CodeForces – 471D]   【KMP】

    题解:将幅度记录(就是相邻两数的差值),再KMP。

    //AC  by  lyy:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<limits.h>
    #define CLR(a,b) memset((a),(b),sizeof((a)))
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    const int mod = 1e9+7;
    double eps = 1e-8;
    int n, m;
    int ans;
    int a[N], b[N];
    
    int nex[N];
    void Next() {
        int i, j;
        j = nex[0] = -1;
        i = 0;
        while(i < m) {
            while(-1 != j && b[i] != b[j])
                j = nex[j];
            nex[++i] = ++j;
        }
    }
    void kmp(){
        int i = 0, j = 0;
        Next();
        while(i < n){
            if(j == -1 || a[i] == b[j]){
                i++; j++;
            }
            else
                j = nex[j];
            if(j == m) {
                ans++;
            }
        }
    }
    
    int main(){
        int i, j;
        scanf("%d%d", &n, &m);
        for(i = 0; i < n; ++i) scanf("%d", &a[i]);
        for(i = 0; i < m; ++i) scanf("%d", &b[i]);
        if(m == 1) { printf("%d
    ", n); return 0; }
    
        for(i = 0; i < n-1; ++i) {
            a[i] = a[i+1] - a[i];
        }
        for(j = 0; j < m-1; ++j) {
            b[j] = b[j+1] - b[j];
        }
        ans = 0;
        --n, --m;
        kmp();
        printf("%d
    ", ans);
        return 0;
    }

    K – Reclamation   [CodeForces – 325D]   【并查集】

    //yy:kn说这题他去年听学姐讲过但是没在意听,然后开始想思路,说先在右边加上最左边一列,再在两边设两个源点并分别把两边的格子连接,然后每放一个障碍就检查其周围八个格子是否有跟两个源点连接,如果有就不能放这个障碍……总之就是,只要障碍左右都连通了,那么圆柱的上顶和下底就会不连通,就不能放这个障碍,,然后他敲了发并查集没过,然后我们又挂了orz

    L - Crazy Town   [CodeForces – 499C]   【几何】

    题意:有很多直线会把平面划分成很多块,给出直线方程的系数,起点和终点坐标,问最少走过几块可以从起点到终点

    题解:分别把起点和终点代入每个直线方程,判断两点是否在直线两侧,是的话答案加一。

    //yy:把long long改成了double就过了、、水题我总能以各种姿势先WA一下。。

    AC  by  lyy:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<limits.h>
    #define CLR(a,b) memset((a),(b),sizeof((a)))
    using namespace std;
    typedef long long ll;
    const int N = 1e5;
    const int mod = 1e9+7;
    double eps = 1e-8;
    double x1, y1, x2, y2;
    int main() {
        int n;
        scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
        scanf("%d", &n);
        int ans = 0;
        while(n--) {
            double a, b, c;
            scanf("%lf%lf%lf", &a, &b, &c);
            if((a*x1+b*y1+c) * (a*x2+b*y2+c) < eps)
                ans++;
        }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    一个好的时间函数
    Codeforces 785E. Anton and Permutation
    Codeforces 785 D. Anton and School
    Codeforces 510 E. Fox And Dinner
    Codeforces 242 E. XOR on Segment
    Codeforces 629 E. Famil Door and Roads
    Codeforces 600E. Lomsat gelral(Dsu on tree学习)
    Codeforces 438D The Child and Sequence
    Codeforces 729E Subordinates
    【ATcoder】D
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/6746680.html
Copyright © 2011-2022 走看看