淘汰赛反思+题解(持续更新。。。)

这次实验室淘汰赛打完之后由于太菜我们还被学长训了一顿,反思很多,痛定思痛,总结了一下自己的不足,有的题比赛时就是想不出以至于挂机,但是第二天早上补题时看一眼就想出来了,很多原因, 牢记教训。

B题

找规律,发现和二进制有某种联系。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXM 256 + 10
#define MAXN 100 + 10
 
using namespace std;
typedef long long ll;
 
ll k, n;
 
ll get(ll n)
{
    ll ans = 0, dig = 1;
    while(n){
        ans += (n & 1) * dig;
        dig *= 10;
        n >>= 1;
    }
    return ans;
}
 
int main()
{
    scanf("%lld %lld", &k, &n);
    ll temp = get(n);
    ll ans = 0, dig = 0;
    while(temp){
        if(temp % 10) ans += pow(k, dig);
        temp /= 10;
        dig ++;
    }
    printf("%lld\n", ans);
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1269
    User: 1707004444
    Language: C++
    Result: 正确
    Time:0 ms
    Memory:2204 kb
****************************************************************/

D题

可以将子问题转化为01背包问题,然后dfs枚举状态,枚举方法时注意不要在dfs里面放for循环枚举,具体看代码注释部分。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 2800 + 10
#define MAXN 28 + 10
 
using namespace std;
typedef long long ll;
 
int n, m;
int w[MAXN], vis[MAXN];
int dp[MAXM];
int total, ans;
 
void deal(int now, int num)
{
    if(now > n) return ;
 
    if(num == 0){
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        for(int i = 0; i < n; i ++){
            if(!vis[i]){
                for(int j = total; j >= w[i]; j --){
                    dp[j] |= dp[j-w[i]];
                }
            }
        }
 
        int temp = 0;
        for(int i = 1; i <= total; i ++)
            if(dp[i]) temp ++;
        ans = max(ans, temp);
 
        return ;
    }
 
    /*
    这样跑一遍会超时
    for(int i = 0; i < n; i ++){
        if(!vis[i]){
            vis[i] = 1;
            deal(num - 1);
            vis[i] = 0;
        }
    }
    */

    deal(now + 1, num);  //不剔除该学生
 
    vis[now] = 1;        //剔除该学生
    deal(now + 1, num - 1);
    vis[now] = 0;
}
 
int main()
{
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i ++) scanf("%d", &w[i]), total += w[i];
 
    deal(0, m);
 
    printf("%d\n", ans);
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1268
    User: 1707004444
    Language: C++
    Result: 正确
    Time:796 ms
    Memory:2032 kb
****************************************************************/

E题

动态规划。dp[ i ][ a[ i ] ] 保存的是第 i 位取 a[ i ] 时的最优解。

                           dp[i][a[i]]=dp[i-1][a[i-1]]+score[a[i-1]][a[i]]               when a[i] != -1 && a[i-1] != -1

dp[ i ][ a[ i ] ] =    dp[i][a[i]]=max(dp[i][a[i]],dp[i-1][j]+score[j][a[i]])      when a[i] != -1 && a[i-1] == -1

                           dp[i][j]=max(dp[i][j],dp[i-1][a[i-1]]+score[a[i-1]][j])   when a[i] == -1 && a[i-1] != -1

                           dp[i][j]=max(dp[i][j],dp[i-1][k]+score[k][j])                when a[i] == -1 && a[i-1] == -1

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 200 + 10
#define MAXN 1000 + 10
 
using namespace std;
typedef long long ll;
 
int t, n, m;
int f[MAXM][MAXM];
int a[MAXN];
int dp[MAXN][MAXM];
 
int main()
{
    scanf("%d", &t);
    while(t --){
 
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= m; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &f[i][j]);
 
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
 
        memset(dp, 0, sizeof(dp));
        for(int i = 2; i <= n; i ++){
            if(a[i-1] != -1 && a[i] != -1){
                dp[i][a[i]] = dp[i-1][a[i-1]] + f[a[i-1]][a[i]];
            }
            else if(a[i-1] != -1 && a[i] == -1){
                for(int j = 1; j <= m; j ++){
                    dp[i][j] = max(dp[i][j], dp[i-1][a[i-1]] + f[a[i-1]][j]);
                }
            }
            else if(a[i-1] == -1 && a[i] != -1){
                for(int j = 1; j <= m; j ++){
                    dp[i][a[i]] = max(dp[i][a[i]], dp[i-1][j] + f[j][a[i]]);
                }
            }
            else{
                for(int j = 1; j <= m; j ++){
                    for(int k = 1; k <= m; k ++){
                        dp[i][j] = max(dp[i][j], dp[i-1][k] + f[k][j]);
                    }
                }
            }
        }
 
        int ans = 0;
        for(int i = 1; i <= m; i ++)
            ans = max(ans, dp[n][i]);
        printf("%d\n", ans);
    }
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1267
    User: 1707004444
    Language: C++
    Result: 正确
    Time:436 ms
    Memory:3024 kb
****************************************************************/

F题

树状数组板子题

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 100000 + 10
 
using namespace std;
typedef long long ll;
 
int tree[MAXN], vis[MAXN];
int n;
 
void add(int k, int num)
{
    while(k <= MAXN){
        tree[k] += num;
        k += k & -k;
    }
}
 
int sum(int k){
    int ans = 0;
    while(k){
        ans += tree[k];
        k -= k & -k;
    }
    return ans;
}
 
int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i ++){
        int temp; scanf("%d", &temp);
        add(temp, 1);
        vis[temp] ++;
        int ans = sum(temp);
        ans -= (vis[temp] - 1);
        printf("%d%c", ans, i == n - 1 ? '\n' : ' ');
    }
 
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1270
    User: 1707004444
    Language: C++
    Result: 正确
    Time:264 ms
    Memory:2800 kb
****************************************************************/

G题

对于每个非叶子节点,如果他和他的所有叶子子节点满足条件,那么这棵树就满足条件。bfs每次把子节点不是叶子节点的压入队列。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 2000000 + 10
 
using namespace std;
typedef long long ll;
 
vector<int> G[MAXN];
 
int main()
{
    int n; scanf("%d", &n);
    for(int i = 1; i < n; i ++){
        int a, b; scanf("%d %d", &a, &b);
        G[a].push_back(b);
    }
 
    queue<int> Q;
    Q.push(1);
    int ans = 0;
    while(!Q.empty()){
        int fro = Q.front();
        Q.pop();
        int son = 0;
        for(int i = 0; i < G[fro].size(); i ++){
            if(G[G[fro][i]].size() == 0)
                son ++;
            else{
                Q.push(G[fro][i]);
            }
        }
        ans += (son + 1) / 2;
    }
    printf("%d\n", ans);
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1265
    User: 1707004444
    Language: C++
    Result: 正确
    Time:560 ms
    Memory:111464 kb
****************************************************************/

H题

优先队列。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 100000 + 10
 
using namespace std;
typedef long long ll;
 
struct node{
    int a, b, c;
    int x;
    int total;
    bool operator < (const node &a) const{
        return total > a.total;
    }
}no[MAXN];
 
int deal(node n)
{
    return n.a * n.x * n.x + n.b * n.x + n.c;
}
 
int main()
{
    int n, m; scanf("%d %d", &n, &m);
    priority_queue<node> Q;
    for(int i = 0; i < n; i ++){
        scanf("%d %d %d", &no[i].a, &no[i].b, &no[i].c);
        no[i].x = 1; no[i].total = deal(no[i]);
        Q.push(no[i]);
    }
 
    int ans = 0;
    while(m --){
        node temp = Q.top();
        Q.pop();
        ans += temp.total;
        temp.x ++;
        temp.total = deal(temp);
        Q.push(temp);
    }
    printf("%d\n", ans);
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1264
    User: 1707004444
    Language: C++
    Result: 正确
    Time:40 ms
    Memory:7892 kb
****************************************************************/

J题

带权并查集。将每个节点的父亲和到父亲的距离用数组保存下来。分情况合并,具体看代码。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 50000 + 10
 
using namespace std;
typedef long long ll;
 
int father[MAXN] = {0};
int d[MAXN] = {0}, f = 0, ans = 0;
 
int get(int x)
{
    if(father[x] == x) return x;
 
    f += d[x];
    return get(father[x]);
}
 
void unions(int x, int y, int dd)
{
    f = 0; int r_x = get(x); int fx = f;
    f = 0; int r_y = get(y); int fy = f;
    if(r_x == r_y){
        if(fx - fy != dd){
            ans ++;
            return ;
        }
    }
    else{
        if(fx >= fy + dd){
            father[r_y] = r_x;
            d[r_y] = fx - dd - fy;
        }
        else{
            if(fx > dd){
                father[r_x] = r_y;
                d[r_x] = dd + fy - fx;
            }
            else{
                father[r_x] = y;
                d[r_x] = dd - fx;
            }
        }
    }
}
 
int main()
{
    int n, m; scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i ++) father[i] = i;
    for(int i = 0; i < m; i ++){
        int a, b, x; scanf("%d %d %d", &a, &b, &x);
        unions(a, b, x);
    }
    printf("%d\n", ans);
}
 
/*
 
The WAM is F**KING interesting .
 
*/
 
/**************************************************************
    Problem: 1275
    User: 1707004444
    Language: C++
    Result: 正确
    Time:40 ms
    Memory:2408 kb
****************************************************************/

猜你喜欢

转载自blog.csdn.net/ooB0Boo/article/details/83344020
今日推荐