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

A

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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<int> 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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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<int> G[qq], f[qq];
int deg[qq], n, m;
LL dp[qq];
void Topu() {
    queue<int> 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 <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>
 
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值