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\n", ans);
            }
        }
        else {
            if(visy[p])
                puts("0");
            else{
                visy[p] = 1;
                LL ans = 1ll * cntx * p + sumx;
                sumy -= p;
                --cnty;
                printf("%lld\n", 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\n", sum);
                    return 0;
                }
            }

        }
    }
    sum += 50 * k;
    printf("%d\n", 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\n", 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] = '\0';
    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\n", 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] = '\0';
        ans2[n] = '\0';
        printf("%s\n", ans1);
        cout << flush;
        scanf("%d", &t);
        if(t != n){
            printf("%s\n", 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\n", l-1);
    
    return 0;
}
View Code

 

posted @ 2018-11-19 14:00  Schenker  阅读(284)  评论(0编辑  收藏  举报