• Gym 100851 题解


    A: Adjustment Office

    题意:在一个n*n的矩阵,每个格子的的价值为 (x+y), 现在有操作取一行的值,或者一列的值之后输出这个和, 并且把这些格子上的值归0。

    题解:模拟, 分成xy轴就好了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("adjustment.in","r",stdin); freopen("adjustment.out","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e6 + 100;
    LL sumx, sumy;
    int cntx, cnty;
    int visx[N], visy[N];
    char op[5];
    int p;
    int main(){
        Fopen;
        int n, q;
        scanf("%d%d", &n, &q);
        sumx = sumy = (1ll+n)*n / 2;
        cntx = cnty = n;
        while(q--){
            scanf("%s%d", op, &p);
            if(op[0] == 'R'){
                if(visx[p])
                    puts("0");
                else{
                    visx[p] = 1;
                    LL ans = 1ll * cnty * p + sumy;
                    sumx -= p;
                    --cntx;
                    printf("%lld
    ", ans);
                }
            }
            else {
                if(visy[p])
                    puts("0");
                else{
                    visy[p] = 1;
                    LL ans = 1ll * cntx * p + sumx;
                    sumy -= p;
                    --cnty;
                    printf("%lld
    ", ans);
                }
            }
        }
        return 0;
    }
    View Code

    D:题解传送门

    E:Easy Problemset

    题意:有n组题目,每组题目有pi个题目,然后每个题目有一个[0, 49]的难度, 现在轮着选这些题, 当入选题目的总难度小于等于当天题目的时候,就把这个题目加入入选题目, 如果一组题目用完了就用50的题目去填充,当选完了所有题目之后还没有满足条件,就用难度50的题目填充剩下的。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("easy.in","r",stdin); freopen("easy.out","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int p[13][15];
    int a[100];
    int main(){
        Fopen;
        int n, k;
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
            for(int j = 1; j <= a[i]; ++j)
                scanf("%d", &p[i][j]);
            for(int j = a[i]+1; j < 15; ++j)
                p[i][j] = 50;
        }
        int sum = 0;
        for(int j = 1; j < 15; ++j){
            for(int i = 1; i <= n; ++i){
                if(sum <= p[i][j]){
                    sum += p[i][j];
                    --k;
                    if(k == 0){
                        printf("%d
    ", sum);
                        return 0;
                    }
                }
    
            }
        }
        sum += 50 * k;
        printf("%d
    ", sum);
        return 0;
    }
    View Code

    F:Froggy Ford

    题意:从图的最左边跑到最右边,只能在点(河岸),现在可以新增一个点,问你从最左边跳到最右边,最长跳远最小可以是多少。

    题解:我们从左边跑一遍n^2的最短路,然后从右边跑一遍最短路,然后再枚举2个点找最优解就好了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("froggy.in","r",stdin); freopen("froggy.out","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1100;
    double e[N][N];
    pll p[N];
    int w, n;
    inline double cal(pll & p1, pll & p2){
        return sqrt(pow(p1.fi-p2.fi, 2) + pow(p1.se-p2.se,2));
    }
    double dis[2][N];
    int vis[N];
    void dijkstra(int st,int op){
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i <= n + 1; ++i)
            dis[op][i] = e[st][i];
        dis[op][st] = 0; vis[st] = 1;
        while(true){
            double min1 = INF;
            int z = -1;
            for(int j = 0; j <= n+1; j++)
                if(!vis[j] && min1 > dis[op][j])
                    z = j, min1 = dis[op][j];
            if(z == -1) break;
            vis[z] = 1;
            for(int j = 0; j <= n; ++j){
                dis[op][j] = min(dis[op][j], max(e[z][j], dis[op][z]));
            }
        }
    }
    
    int main(){
        Fopen;
        scanf("%d%d", &w, &n);
        for(int i = 1; i <= n; ++i)
            scanf("%d%d", &p[i].fi, &p[i].se);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j){
                e[i][j] = cal(p[i], p[j]);
            }
        for(int i = 1; i <= n; ++i){
            e[i][0] = e[0][i] = p[i].fi;
            e[i][n+1] = e[n+1][i] = w - p[i].fi;
        }
        e[n+1][0] = e[0][n+1] = w;
        dijkstra(0,0);
        dijkstra(n+1,1);
        int p1, p2;
        double llen = INF;
        for(int i = 0; i <= n + 1; ++i){
            for(int j = 0; j <= n+1; ++j){
                double tmp = max3(dis[0][i], dis[1][j], e[i][j]/2.0);
                if(tmp < llen){
                    llen = tmp;
                    p1 = i, p2 = j;
                }
            }
        }
    
        int ansx, ansy;
        if(p1 > p2) swap(p1, p2);
        if(p1 == 0){
            ansx = p[p2].fi;
            ansy = p[p2].se*2;
        }
        else if(p2 == n+1){
            ansx = p[p1].fi + w;
            ansy = p[p1].se * 2;
        }
        else {
            ansx = p[p1].fi + p[p2].fi;
            ansy = p[p1].se + p[p2].se;
        }
        if(ansx&1) printf("%d.5 ", ansx/2);
        else printf("%d ", ansx/2);
        if(ansy&1) printf("%d.5", ansy/2);
        else printf("%d", ansy/2);
        return 0;
    }
    View Code

    G:Generators

    题意:有n个生成序列,现在要你在这n个生成序列每个都找到一个值相加,要求和在不能被k整除的情况下最大。

    题解:暴力跑出循环节,找到每个序列的最大值和次大值,最大值和次大值的差不能被k整除,然后把每个序列的最大值相加, 然后如果被k整除,就找一个次小值去替换。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("generators.in","r",stdin); freopen("generators.out","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 11000;
    int vis[1005];
    int A[N];
    int p[N][2], v[N][2];
    int main(){
        Fopen;
        int n, k, a, b, c, x, m;
        scanf("%d%d", &n, &k);
        int sum = 0;
        for(int i = 1; i <= n; ++i){
            scanf("%d%d%d%d", &x, &a, &b, &c);
            m = 0;
            while(!vis[x]){
                A[++m] = x;
                vis[x] = 1;
                x = (a*x + b) % c;
            }
            for(int j = 1; j <= m; ++j){
                vis[A[j]] = 0;
                if(v[i][0] <= A[j]){
                    v[i][0] = A[j];
                    p[i][0] = j;
                }
            }
            sum += v[i][0];
            for(int j = 1; j <= m; ++j){
                if(v[i][0] == A[j]) continue;
                if((v[i][0]-A[j])%k != 0 && v[i][1] <= A[j]){
                    v[i][1] = A[j];
                    p[i][1] = j;
                }
            }
        }
        if(sum % k == 0){
            int tmp = 0, pos, val = 0;
            for(int i = 1; i <= n; ++i){
                if(p[i][1] == 0) continue;
                tmp = sum - v[i][0] + v[i][1];
                if(tmp > val){
                    val = tmp;
                    pos = i;
                }
            }
            if(val != 0){
                sum = val;
                p[pos][0] = p[pos][1];
            }
        }
        if(sum%k == 0) puts("-1");
        else {
            printf("%d
    ", sum);
            for(int i = 1; i <= n; ++i)
                printf("%d ", p[i][0]-1);
        }
    
        return 0;
    }
    View Code

    J:Jump 交互题

    题意:现在有一个长度为偶的01序列,然后要求你每次输出一个序列,如果这个输出序列的和原序列的相同的位置的个数是 n 或者 n/2 的话会输出这个值否者输出0。

    题解:先rand找到一个n/2的,然后就假设第一位值正确的,然后枚举每个位置的变化。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    char s[N];
    char ans1[N], ans2[N];
    int f = 0, n, t;
    void boom(){
        for(int i = 0; i < n; ++i) s[i] = '0' + ((rand()%2));
    }
    int main(){
        srand(19990629);
        scanf("%d", &n);
        s[n] = '';
        while(1){
            boom();
            puts(s);
            cout << flush;
            scanf("%d", &f);
            if(f == n) return 0;
            if(f == n/2) break;
        }
        if(f == n/2){
            ans1[0] = s[0];
            ans2[0] = '0' + '1' - s[0];
            s[0] = '0' + '1' - s[0];
            for(int i = 1, t; i < n; ++i){
                s[i] = '0' + '1' - s[i];
                printf("%s
    ", s);
                cout << flush;
                scanf("%d", &t);
                if(t == n/2) {
                    ans1[i] = s[i];
                    ans2[i] = '0' + '1' - s[i];
                }
                else {
                    ans1[i] = '0' + '1' - s[i];
                    ans2[i] = s[i];
                }
                s[i] = '0' + '1' - s[i];
            }
            ans1[n] = '';
            ans2[n] = '';
            printf("%s
    ", ans1);
            cout << flush;
            scanf("%d", &t);
            if(t != n){
                printf("%s
    ", ans2);
                cout << flush;
            }
        }
        return 0;
    }
    View Code

    K:King’s Inspection

    题意:有一幅图 n个点的图,m个单向边, 问能不能从1号点出发,然后绕一圈,经过其他的所有的点一次,然后会到一号点。

    题解:因为最多是 n+20条边,我们先判断一下有没有 入度为0 或者 出度为0有就是非法的。

    20个多的边 如果都走一遍 也就是 2^20次方 ≈ 1e6, 但是 我们如果遍历其他的链, 那么要1e6 * 1e5 就不行了。

    所以我们把这些单链都缩点,缩成一条边,这样在图合法的前提下,我们的图就会很小,就可以爆搜了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("king.in","r",stdin); freopen("king.out","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    vector<int> e[N];
    vector<pll> vc[N];
    int in[N], out[N], ok[N], vis[N];
    int nt[N];
    int sta[N];
    int n, m, u, v;
    void P(int k){
        for(int i = 1; i <= k; ++i){
            printf("%d ", sta[i]);
            if(ok[sta[i]]){
                int x = nt[sta[i]];
                while(x){
                    printf("%d ", x);
                    x = nt[x];
                }
            }
        }
        printf("1");
    }
    void dfs(int u, int k, int num){
        sta[k] = u;
        vis[u] = 1;
        for(int i = 0; i < vc[u].size(); ++i){
            int v = vc[u][i].fi, ct = vc[u][i].se;
            if(vis[v]){
                if(v == 1 && num + ct  == n){
                    P(k);
                    exit(0);
                }
                continue;
            }
            vis[v] = 1;
            dfs(v, k+1, num+1+ct);
            vis[v] = 0;
        }
    }
    int main(){
        Fopen;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; ++i){
            scanf("%d%d", &u, &v);
            in[v]++, out[u]++;
            e[u].pb(v);
        }
        for(int i = 1; i <= n; ++i){
            if(in[i] < 1 || out[i] < 1) {
                puts("There is no route, Karl!");
                return 0;
            }
            ok[i] = (in[i] == 1 && out[i] == 1);
        }
        ok[1] = 0;
        for(int i = 1; i <= n; ++i){
            if(vis[i]) continue;
            if(ok[i]){
                int to = e[i][0], ct = 0, now = i;
                vis[i] = 1;
                while(ok[to]){
                    if(vis[to]){
                        if(to == i) break;
                        nt[now] = to;
                        ct += vc[to][0].se + 1;
                        to = vc[to][0].fi;
                    }
                    else {
                        ct++;
                        vis[to] = 1;
                        nt[now] = to;
                        now = to;
                        to = e[to][0];
                    }
                }
                vc[i].pb({to,ct});
            }
            else {
                for(int j = 0; j < e[i].size(); ++j){
                    vc[i].pb({e[i][j],0});
                }
            }
        }
        memset(vis, 0, sizeof vis);
        dfs(1, 1, 1);
        puts("There is no route, Karl!");
        return 0;
    }
    /*
    10 11
    10 8
    5 4
    9 1
    4 3
    7 2
    2 6
    6 5
    8 9
    1 7
    10 3
    3 10
    */
    View Code

    L:Landscape Improved

    题解:直接模拟就好了,我们可以发现不好同时维护左边的信息,维护右边的信息,所以我们可以把他们分开来处理,最后在把所有的信息合在一起。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    LL h[N], hh[N];
    LL m;
    int n;
    bool check(LL x){
        memset(hh, 0, sizeof hh);
        LL s = 0, r = 2,  l = n-1;
        for(int i = 1; i <= n; ++i){
            if(r == i) r = i+1, s = 0;
            while(r <= n && h[r] < x - (r-i)){
                s += x - (r-i) - h[r];
                r++;
            }
    //        cout << i << ' ' << r << ' ' << s << endl;
            if(r > n) hh[i] = INF;
            else {
                hh[i] = s;
                s -= max(0ll, (x-1)-h[i+1]);
    
                s += max(0ll, (r-1)-(i+1));
    //            cout << s << endl;
            }
        }
        s = 0;
        for(int i = n; i >= 1; --i){
            if(l == i) l = i-1, s = 0;
            while(l >= 1 && h[l] < x - (i-l)){
                s += x - (i-l) - h[l];
                l--;
            }
            if(l < 1) hh[i] = INF;
            else {
                hh[i] += s;
                s -= max(0ll, (x-1)-h[i-1]);
                s += max(0ll, (i-1)-(l+1));
            }
        }
        for(int i = 1; i <= n; ++i){
            hh[i] += max(0ll, x-h[i]);
            if(hh[i] <= m) return true;
        }
        return false;
    }
    int main(){
        freopen("landscape.in","r",stdin);
        freopen("landscape.out","w",stdout);
        scanf("%d%lld", &n, &m);
        LL mx = 0;
        for(int i = 1; i <= n; ++i){
            scanf("%lld", &h[i]);
            mx = max(mx, h[i]);
        }
    
        LL l = mx+1, r = m + mod;
        while(l <= r){
            LL mid = l+r >> 1;
            if(check(mid)) l = mid + 1;
            else r = mid - 1;
        }
        printf("%lld
    ", l-1);
        
        return 0;
    }
    View Code
  • 相关阅读:
    SVN使用指引(Windows)
    Android开发14——监听内容提供者ContentProvider的数据变化
    Android开发13——内容提供者ContentProvider的基本使用
    Android开发12——Andorid中操作数据库的insert的两种方法以及nullColumnHack
    Android开发11——手机横屏和竖屏与android:configChanges
    Android开发10——Activity的跳转与传值
    Android开发9——Activity的启动模式
    Android开发8——利用pull解析器读写XML文件
    Android开发7——android.database.CursorIndexOutOfBoundsException:Index -1 requested
    Android开发6——布局中的wrap_content和fill_parent以及match_parent
  • 原文地址:https://www.cnblogs.com/MingSD/p/9982785.html
Copyright © 2020-2023  润新知