西南交通大学第十三届ACM决赛-重现赛

A

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e6 + 10;
const int INF = 1e9 + 10;
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        int n, w, d;    scanf("%d%d%d", &n, &w, &d);
        int sum1 = 0, sum2 = 0;
        for(int x, i = 1; i <= n; ++i) {
            scanf("%d", &x);
            sum1 += x;
        }
        for(int x, i = 1; i <= n; ++i) {
            scanf("%d", &x);
            sum2 += x;
        }
        if(sum1 <= w && sum2 <= d) {
            puts("YES");
        } else {
            puts("NO");
        }
    }
    return 0;
}

B

记录每行每列所填的数,然后记录一下时间戳,输出的时候对于存在时间戳的输出时间戳晚的,没有时间戳的就是0

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 500 + 10;
const int INF = 1e9 + 10;
int row[qq], colum[qq];
int idr[qq], idc[qq];
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        int n, q;   scanf("%d%d", &n, &q);
        mst(idr, -1), mst(idc, -1);
        for(int op, a, b, i = 0; i < q; ++i) {
            scanf("%d%d%d", &op, &a, &b);
            if(op == 1) {
                row[a] = b;
                idr[a] = i;
            } else {
                colum[a] = b;
                idc[a] = i;
            }
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                if(j != 1)  printf(" ");
                if(idr[i] == -1 && idc[j] == -1) {
                    printf("0");
                } else if(idr[i] != -1 && idc[j] != -1) {
                    if(idr[i] > idc[j]) {
                        printf("%d", row[i]);
                    } else {
                        printf("%d", colum[j]);
                    }
                } else {
                    if(idr[i] == -1) {
                        printf("%d", colum[j]);
                    } else {
                        printf("%d", row[i]);
                    }
                }
            }
            puts("");
        }
    }
    return 0;
}

D

题意:选出一些数 要求和是3600的倍数

思路:可以知道n > 3600的时候一定可以,我们可以求前缀和然后对3600取余,根据抽屉原理可知一定存在两个前缀和取余后结果是一样,也就证明一定可以满足选出数的和是3600的倍数,n <= 3600 直接暴力

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const int INF = 1e9 + 10;
bool dp[3600 + 10][3600 + 10];
int num[qq];
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        int n;  scanf("%d", &n);
        mst(dp, false);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", num + i);
            num[i] %= 3600;
        }
        if(n > 3600) {
            puts("YES");
            continue;
        }
//      dp[0][0] = true;
        for(int i = 1; i <= n; ++i) {
            dp[i][num[i]] = true;
            for(int j = 0; j < 3600; ++j) {
                if(!dp[i - 1][j])   continue;
                dp[i][j] =  true;
                dp[i][(j + num[i]) % 3600] = true;
            }
        }
        if(dp[n][0])    puts("YES");
        else    puts("NO");
    }
    return 0;
}

E

题意:n个点n - 1条边,n是偶数,要求分成把点n / 2对,使得每对之间的距离和最小

思路:这题直接考虑点之间如何分配很不好搞,我们考虑每一条边的是否存在贡献,对于每一个结点如果它的子结点个数是偶数(包括它自身)那么这个结点连接着它父结点的这条边是不是不需要? 是的,因为这颗子树自身可以完成配对,如果是奇数那么这颗子树中肯定有结点它的配对结点肯定不再这颗子树中,所以这条边的权值要加上

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e4 + 10;
const int INF = 1e9 + 10;
vector G[qq], f[qq];
int num[qq];
LL ans;
void Init(int n) {
    for(int i = 0; i <= n; ++i) {
        G[i].clear();
        f[i].clear();
        num[i] = 0;
    }
}
void Dfs(int u, int fa, int dis) {
    int sz = G[u].size();
    for(int i = 0; i < sz; ++i) {
        int v = G[u][i];
        if(v == fa) continue;
        Dfs(v, u, f[u][i]);
        num[u] += num[v];
    }
    num[u]++;
    if(num[u] & 1)  ans += dis;
}
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        int n;  scanf("%d", &n);
        Init(n);
        for(int a, b, c, i = 1; i < n; ++i) {
            scanf("%d%d%d", &a, &b, &c);
            G[a].pb(b), f[a].pb(c);
            G[b].pb(a), f[b].pb(c);
        }
        ans = 0;
        Dfs(1, -1, 0);
        printf("%lld\n", ans);
    }
    return 0;
}

F

因为是一个非递减的序列所以可以想象肯定是第k个位置的数向前移即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const int INF = 1e9 + 10;
LL pre[qq], num[qq];
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        int n, k;   scanf("%d%d", &n, &k);
        pre[0] = 0;
        LL tot = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%lld", num + i);
            tot += (LL)i * num[i];
            pre[i] = pre[i - 1] + num[i];
        }
        LL p = 0;
        for(int i = 1; i <= k; ++i) {
            p += (LL)i * num[i];
        }
        LL maxn = -1;
        for(int i = k + 1; i <= n; ++i) {
            LL tmp = (tot - p - num[i] * (LL)i);
            tmp += (p + (pre[i - 1] - pre[i - 1 - k]) + num[i] * (LL)(i - 1 - k + 1));
            maxn = max(maxn, tmp);
            p -= num[i - k] * (LL)(i - k) + num[i] * (LL)i;
        }
        printf("%lld\n", maxn);
    }
    return 0;
}



H

求一个有向图的最长链,路径有负数,但还是一样的处理

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e3 + 10;
const int INF = 1e9 + 10;
vector G[qq], f[qq];
int deg[qq], n, m;
LL dp[qq];
void Topu() {
    queue Q;
    for(int i = 0; i < n; ++i) {
        if(!deg[i]) Q.push(i);
    }
    while(!Q.empty()) {
        int u = Q.front();
        Q.pop();
        int sz = G[u].size();
        for(int i = 0; i < sz; ++i) {
            int v = G[u][i];
            dp[v] = max(dp[v], max(dp[u] + (LL)f[u][i], (LL)f[u][i]));
            deg[v]--;
            if(deg[v] == 0) Q.push(v);
        }
    }
}
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; ++i) {
            G[i].clear();
            f[i].clear();
        }
        mst(deg, 0);
        for(int a, b, c, i = 1; i <= m; ++i) {
            scanf("%d%d%d", &a, &b, &c);
            deg[b]++;
            G[a].pb(b), f[a].pb(c);
        }
        mst(dp, 0);
        Topu();
        LL maxn = 0;
        for(int i = 0; i < n; ++i) {
            maxn = max(maxn, dp[i]);
        }
        printf("%lld\n", maxn);
    }
    return 0;
}



K

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 300 + 10;
const int INF = 1e9 + 10;
int ct[qq], num[qq];
int isvis[qq];
 
int main(){
    int t;  scanf("%d", &t);
    while(t--) {
        int n, k, q;    scanf("%d%d%d", &n, &k, &q);
        mst(ct, 0);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", num + i);
            ct[num[i]]++;
        }
        int ans = 0;
        for(int i = 1; i <= 100; ++i) {
            int l = i, r = i + k - 1;
            int sum = 0;
            for(int j = l; j <= r; ++j) {
                sum += ct[j];
            }
            if(sum >= q) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(线上比赛)