2025团体程序设计天梯赛总结

这次天梯赛只拿了197分,本来还想着冲国2的,结果只有国3。

开赛卡了好久,一直看不到题,等到正常了看到只剩2个小时左右了l1还没写完有点慌(后来延时了1小时)
主要有几道l1的题没能第一发ac导致有点浪费时间,不过差1,2个点我就跳了,后来延时1h感觉时间还挺充足的,最后剩1h准备开l3题。

到这个时候问题来了 第一眼看l3-1是个图论感觉没那么好做,就去看l3-2,一开始思路想错了想的递推或者找公式,5分钟暂时没想好,发现l1-6之前跳了,就想着先把l1-6做了,想着数组操作直接用python方便,结果3个操作巨麻烦,写了40min过了样例交上去一个点没过,这下真的心态爆炸了,剩20min想着赶紧做l3,仔细一看l3-1发现是弗洛伊德算法紧急秒了一个,最后没时间调错了一个9分点,只能197遗憾离场。

不过今年确实比去年进步很多,感觉自己还是手速慢了点,以及对有些数组下标处理想的不清楚,后来补题发现l3-2就是个非常简单的前缀和,以后比赛还是不应该乱换题,感觉不难的题就应该多想想,以及l1-6其实用c++stl里内置的函数其实很简单但是因为自己对stl许多函数不熟悉只能手写导致变复杂了。

以下是部分补题

l1-6
用python写了个数组处理发现后两个点会超时,懒得再改c++就直接让ai改成c++了,本题就是暴力模拟3种操作,c++不会超时

点击查看代码
#include <iostream>  
#include <vector>  
#include <algorithm>  

using namespace std;  

int main() {  
    int N, M;  
    cin >> N >> M;  

    // 存储输入的初始序列  
    vector<int> sequence(N);  
    for (int i = 0; i < N; i++) {  
        cin >> sequence[i];  
    }  

    // 处理 M 次操作  
    for (int op = 0; op < M; op++) {  
        int operationType;  
        cin >> operationType;  

        switch (operationType) {  
            case 1: {  
                // 查找-替换操作  
                int L1;  
                cin >> L1;  
                vector<int> searchSeq(L1);  
                for (int i = 0; i < L1; i++) {  
                    cin >> searchSeq[i];  
                }  

                int L2;  
                cin >> L2;  
                vector<int> replaceSeq(L2);  
                for (int i = 0; i < L2; i++) {  
                    cin >> replaceSeq[i];  
                }  

                // 查找并替换第一个匹配的子序列  
                bool found = false;  
                for (int i = 0; i <= sequence.size() - L1; i++) {  
                    if (equal(sequence.begin() + i, sequence.begin() + i + L1, searchSeq.begin())) {  
                        sequence.erase(sequence.begin() + i, sequence.begin() + i + L1);  
                        sequence.insert(sequence.begin() + i, replaceSeq.begin(), replaceSeq.end());  
                        found = true;  
                        break;  
                    }  
                }  
                break;  
            }  

            case 2: {  
                // 插入平均数操作  
                vector<int> newSequence;  
                for (size_t i = 0; i < sequence.size() - 1; i++) {  
                    newSequence.push_back(sequence[i]);  
                    if ((sequence[i] + sequence[i + 1]) % 2 == 0) {  
                        newSequence.push_back((sequence[i] + sequence[i + 1]) / 2);  
                    }  
                }  
                newSequence.push_back(sequence.back());  
                sequence = newSequence;  
                break;  
            }  

            case 3: {  
                // 翻转操作  
                int l, r;  
                cin >> l >> r;  
                reverse(sequence.begin() + l - 1, sequence.begin() + r);  
                break;  
            }  
        }  
    }  

    // 输出最终结果  
    for (size_t i = 0; i < sequence.size(); i++) {  
        cout << sequence[i];  
        if (i < sequence.size() - 1) cout << " ";  
    }  

    return 0;  
}  

l2-3

熊猫生活需要几个山头的问题
一天只有246060s,考虑差分数组,把时间按秒变成线性的,在每个panda的开始时间+1,结束时间-1,这就是差分数组,求前缀和就能得到每个时间点有几只panda,找最大值就好了
(比赛时做完了,没有存代码)

l2-4

非常简单的dfs,熟悉搜索的会觉得思路很清晰,满足条件的数不多,从高位往低位搜索下一个可能的数,注意要把不整除的剪枝

l3-1
n只有500,可以用floyd算法预处理出所有点间最短路,在转移的时候顺便维护一下路上心情值之和即可,注意最后9分点的问题是当找到点i,j之间有相同长度的最短路时,路上心情值之和是这两条路走最小

点击查看代码
#include<bits/stdc++.h>
//#define INF 0x3f3f3f3f
#define lowbit(x) = ((x)& - (x))
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define x first
#define y second
using namespace std;
typedef long long ll;

const int INF = 1e9;
const int N = 503;
int n,b,m,k;
int w1[N][N],w2[N][N];
int ans1[N],ans2[N];

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int u,v,x,y;
    cin>>b>>n>>m>>k;
    rep(i,1,n){
        rep(j,1,n){
            w1[i][j] = w1[j][i] = INF;
            if(i == j)w1[i][j] = 0;
        }
    }
    rep(i,1,m){
        cin>>u>>v>>x>>y;
        w1[u][v] = w1[v][u] = x;
        w2[u][v] = w2[v][u] = y;
    }
    rep(k,1,n){
        rep(i,1,n){
            rep(j,1,n){
                if(w1[i][j]>=w1[i][k]+w1[k][j]){
                    
                    if(w1[i][j]==w1[i][k]+w1[k][j]){
                        w2[i][j] = max(w2[i][j],w2[i][k]+w2[k][j]);
                    }
                    else{
                        w2[i][j] = w2[i][k]+w2[k][j];
                    }
                    w1[i][j] = w1[i][k]+w1[k][j];
                    w2[j][i] = w2[i][j];
                    w1[j][i] = w1[i][j];
                }
                //if(w1[i][k]+w1[k][j]<=b)w2[i][j] = max(w2[i][j],w2[i][k]+w2[k][j]);
            }
        }
    }
    int p,cnt1 = 0,cnt2 = 0,ma = 0;
    rep(i,1,k){
        cnt1 = cnt2 = 0;
        ma = 0;
        cin>>p;
        rep(j,1,n){
            if(w1[p][j]<=b && j!=p){
                ans1[++cnt1] = j;
                ma = max(ma,w2[p][j]);
            }
        }
        sort(ans1+1,ans1+cnt1+1);
        rep(j,1,cnt1){
            if(w2[p][ans1[j]] == ma )ans2[++cnt2] = ans1[j];
        }
        if(cnt1 == 0){
            cout<<"T_T\n";
            continue;
        }
        //cout<<cnt1<<'\n';
        rep(j,1,cnt1-1)cout<<ans1[j]<<' ';cout<<ans1[cnt1]<<'\n';
        rep(j,1,cnt2-1)cout<<ans2[j]<<' ';cout<<ans2[cnt2]<<'\n';
        
    }
    //cout<<w2[7][5];
	return 0;
}

l3-2

就是要找到每个点对整张图dist之和然后乘以权值
一开始一直在想能不能dp或者公式之类的,最后想到其实就是前缀和
考虑a[i][j]是坐标(i,j)对(1,1)的dist,求a数组前缀和s
那么s[i][j]就是一个ij矩阵里(1,1)的dist之和
n
m的图中点(x,y)可以以x行和y列把矩阵分割成4个小矩阵,(x,y)是这4个矩阵的角的位置,用前缀和求和在减去x行和y列重复计算了的点就是(x,y)对整张图的距离
dis[x][y] = s[x][y] + s[x][m-y+1] + s[n-x+1][y] + s[n-x+1][m-y+1] - (((x-1)x+(y-1)y + (n-x)(n-x+1)+(m-y)(m-y+1))/2)

点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define lowbit(x) = ((x)& - (x))
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
#define x first
#define y second
using namespace std;
typedef long long ll;

int n,m;

ll calc(int x,int y,vector<vector<ll>> & s){
    ll res = 0;
    res += s[x][y] + s[x][m-y+1] + s[n-x+1][y] + s[n-x+1][m-y+1];
    res -= ((x-1)*x+(y-1)*y + (n-x)*(n-x+1)+(m-y)*(m-y+1))/2;
    return res;
}

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    
    cin>>n>>m;
    vector<vector<ll>> dis(n+2,vector<ll>(m+2)),s(n+2,vector<ll>(m+2)),a(n+2,vector<ll>(m+2));
    rep(i,1,n){
        rep(j,1,m)cin>>a[i][j];
    }
    rep(i,0,n)s[i][0] = 0;
    rep(j,0,m)s[0][j] = 0;
    rep(i,1,n){
        rep(j,1,m){
            s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + max(i-1,j-1);
        }
    }
    rep(i,1,n){
        rep(j,1,m){
            dis[i][j] = calc(i,j,s);
        }
    }
    rep(i,1,n){
        rep(j,1,m - 1)cout<<a[i][j] * dis[i][j]<<' ';cout<<a[i][m] * dis[i][m]<<'\n';
    }
	return 0;
}

posted @ 2025-04-26 11:02  明天能下雨吗  阅读(92)  评论(0)    收藏  举报