2025年5月1号vp天梯赛
VP天梯赛
比赛时间3小时。
L1共100分,拿95分;
L2共100分,拿82分;
L3共90分,拿38分;
总共290分,拿199分。
因题目难度原因,部分题目不列举。
L1-6 这不是字符串题
大模拟,不知为啥一个测试点错误一个测试点段错误。
我采用vector只能拿10分,知乎大佬采用string能拿满。
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n,m;cin>>n>>m;
string s;
for(int i=1;i<=n;i++){
int x;cin>>x;
s.push_back(char('a'+x-1));
}
while(m--){
int op;cin>>op;
if(op==1){
int x;cin>>x;
int len=x;
string t;
while(x--){
int k;cin>>k;
t.push_back(char('a'+k-1));
}
int x2;cin>>x2;
int len2=x2;
string t2;
while(x2--){
int k;cin>>k;
t2.push_back(char('a'+k-1));
}
if(s.find(t)==string::npos){
continue;
}else{
s.replace(s.find(t),len,t2);
}
}else if(op==2){
string ne;
for(int i=0;i<s.length()-1;i++){
int x1=s[i]-'a'+1,x2=s[i+1]-'a'+1;
if((x1+x2)%2==0){
ne.push_back(s[i]);
ne.push_back(char((x1+x2)/2+'a'-1));
}else{
ne.push_back(s[i]);
}
}
ne.push_back(s.back());
s=ne;
}else{
int l,r;cin>>l>>r;
l--;
reverse(s.begin()+l,s.begin()+r);
}
}
for(int i=0;i<s.length();i++){
int x=(s[i]-'a'+1);
if(i!=s.length()-1) cout<<x<<" ";
else cout<<x;
}
}
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
while(t--) solve();
return 0;
}
L1-7 大幂数
从最大幂次开始往下遍历。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll n;
cin>>n;
ll x=log2(n);
for(int i=x;i>=1;i--){
ll sum=0;
ll y=1,z=0;
while(sum<n){
sum+=pow(y,i);
y++;
}
if(sum==n){
for(int j=1;j<y;j++){
cout<<j<<'^'<<i;
if(j!=y-1) cout<<'+';
}
return 0;
}
}
cout<<"Impossible for "<<n<<".";
return 0;
}
L1-8 现代战争
又是模拟,采用map或数组存储哪些行和列没有,采用优先队列快速按大小取值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k,xlen,ylen;
struct nod{
int zhi;
int x;
int y;
friend bool operator <(nod a,nod b){
return a.zhi<b.zhi;
}
}a[1001][1001];
map<int,bool> mpx,mpy;
priority_queue<nod> pq;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j].zhi;
a[i][j].x=i;
a[i][j].y=j;
pq.push(a[i][j]);
}
}
while(k--){
nod z=pq.top();pq.pop();
while(!(mpx[z.x]==0&&mpy[z.y]==0)&&!pq.empty()){
z=pq.top();pq.pop();
}
mpx[z.x]=1,mpy[z.y]=1;
xlen++,ylen++;
}
int xx=0,yy=0;
for(int i=1;i<=n;i++){
if(mpx[i]==1) continue;
yy=0;
for(int j=1;j<=m;j++){
if(mpy[j]==1) continue;
cout<<a[i][j].zhi;
yy++;
if(yy!=m-ylen) cout<<" ";
}
cout<<"\n";
}
return 0;
}
L2-1 算式拆解
典。关于算式运算采用stack可简单快速。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string s,str;
stack<string> st;
int a,b=1;
int main(){
cin>>s;
int i=0;
str="";
for(int i=0;i<s.size();i++){
if(s[i]=='('){
if(str!=""){
st.push(str);
str="";
}
a++;
st.push("(");
}else if(s[i]!=')'){
str+=s[i];
}else{
if(str!=""){
st.push(str);
str="";
}
cout<<st.top();
cout<<"\n";
b=1;
st.pop();st.pop();
}
}
return 0;
}
L2-2 三点共线
此题25分赶时间我只拿了16分走人。
知乎大佬题解:
枚举 $y=0$ 和 $y=1$ 时的 $x$,再用 bitset 维护 $y=2$ 时的 $x$ 即可。
和我思路一样,我没去重并且采用unordered_map维护。
const int N = 8e6 + 7;
const int d = 4e6; // 这里把所有点都向右移动4e6即可保证不会出现负数
vector<int> a[2];
bitset<N> pos;
void solve(){
int n; cin >> n;
rep(i, 1, n) {
int x, y; cin >> x >> y;
if(y < 2) a[y].push_back(x);
else pos[x + d] = true;
}
rep(i, 0, 2) sort(all(a[i]));
rep(i, 0, 2) a[i].erase(unique(all(a[i])),a[i].end());
vector<pii> ans;
for(int &x0 : a[0]) {
for(int &x1 : a[1]) {
int x2 = x1 * 2 - x0;
if(pos[x2 + d]) ans.push_back({x1, x0});
}
}
sort(all(ans));
if(!ans.empty()) {
for(auto &[x1, x0] : ans) {
int x2 = x1 * 2 - x0;
cout << '[' << x0 << ", 0] [" << x1 << ", 1] [" << x2 << ", 2]\n";
}
} else cout << -1;
}
L2-3 胖达的山头
前缀和基础题。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int l,r,l1,r1;
map<int,int> mp;
int sum[100000];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int a,b,c;
scanf("%d:%d:%d",&a,&b,&c);
l=a*60*60+b*60+c;
scanf("%d:%d:%d",&a,&b,&c);
r=a*60*60+b*60+c;
sum[l]++;sum[r+1]--;
}
int ans=0;
for(int i=1;i<=86400;i++){
sum[i]+=sum[i-1];
ans=max(sum[i],ans);
}
cout<<ans;
return 0;
}
L2-4 被n整除的n位数
25分拿了16分走人。
知乎大佬题解:
直接暴搜!
我还利用性质花费大量时间拿16分,成nt了
ll n, a, b;
bool f = true;
void dfs(ll x, int dep) {
if(dep == n) {
if(x >= a && x <= b) {
cout << x << '\n';
f = false;
}
return;
}
rep(i, 0, 9) {
if((x * 10 + i) % (dep + 1)) continue;
dfs(x * 10 + i, dep + 1);
}
}
void solve(){
cin >> n >> a >> b;
int st = to_string(a)[0] - '0', ed = to_string(b)[0] - '0';
rep(i, st, ed) dfs(i, 1);
if(f) cout << "No Solution";
}
L3-1 人生就像一场旅行
时间不够了,想dfs拿点分,但题目都还没读明白。
知乎大佬题解:
点的个数为500,没给边的数量,为完全图时会卡掉 Dijkstra。可以用 Floyd 解决此问题。
先走花费最小的点,如果有多个花费最小的点再选沿途心情指数最高的点。天梯赛以前有道思想一模一样的题。L2-001 紧急救援
好吧,我对于最短路算法全部还给教练了。
const int inf = 1e9; // 防止爆int
const int N = 5e2 + 7;
int d[N][N], h[N][N];
void Solution(){
int b, n, m, k; cin >> b >> n >> m >> k;
rep(i, 1, n) rep(j, 1, n) d[i][j] = inf; // Floyd初始化
rep(i, 1, n) d[i][i] = 0;
rep(i, 1, m) {
int x, y, u, v; cin >> x >> y >> u >> v;
d[y][x] = d[x][y] = min(d[x][y], u); // 处理重边
h[y][x] = h[x][y] = max(h[x][y], v);
}
rep(k, 1, n) rep(i, 1, n) rep(j, 1, n) { // Floyd
if(d[i][j] == d[i][k] + d[k][j]) {
h[i][j] = max(h[i][j], h[i][k] + h[k][j]);
} else if(d[i][j] > d[i][k] + d[k][j]) {
d[i][j] = d[i][k] + d[k][j];
h[i][j] = h[i][k] + h[k][j];
}
}
while(k --) { // 处理询问
int x; cin >> x;
vector<int> ans;
rep(y, 1, n) {
if(y == x || d[x][y] > b) continue;
if(ans.size()) cout << ' ';
cout << y;
ans.push_back(y);
}
if(ans.empty()) {
cout << "T_T\n";
continue;
} else cout << '\n';
int hmax = 0;
for(auto &y : ans) hmax = max(hmax, h[x][y]);
bool f = false;
for(auto &y : ans) {
if(h[x][y] != hmax) continue;
if(f) cout << ' ';
cout << y;
f = true;
}
cout << '\n';
}
}
L3-2 影响力
暴力拿了20分,总分30。
知乎大佬题解:
拆成八个方向分别算,
采用递推。$(i,j)$左上方(不含正上正左)的距离和=$(i-1,j-1)$左上方(含正上正左)的距离和+$(i,j)$左上方的方格数量。
似乎也可以说是一个DP。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll cal(int i){
return (i*(i+1ll)/2);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,m;cin>>n>>m;;
vector<vector<ll> > pre(n,vector<ll>(m,0));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
pre[i][j]=cal(i)+cal(j);
if(i&&j) pre[i][j]+=pre[i-1][j-1]+1ll*i*j;
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
ll x;cin>>x;
cout << x * (pre[i][j] + pre[n - 1 - i][j] + pre[i][m - 1 - j] + pre[n - 1 - i][m - 1 - j] - cal(j) - cal(m - 1 - j) - cal(i) - cal(n - 1 - i)) << " \n"[j == m - 1];
}
}
return 0;
}
L3-042 污染大亨
没找到AC题解,只有暴力dfs16分。
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#define int long long
#define double long double
#define _rep(i,a,b) for(int i=(int)(a);i<=(int)b;++i)
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define pp pop_back()
#define fi first
#define se second
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
int n,m,k;
const int N=1e6+10,INF=4e18,P=998244353;
vector<vector<int>>v(N);
int c[N];
int st[N];
int sum;
int qmi(int a,int b,int P){
int res=1;
while(b){
if(b&1)res=res*a%P;
a=a*a%P;
b>>=1;
}
return res;
}
void infact(int u){
sum++;
st[u]++;
for(auto i:v[u]){
infact(i);
}
return;
}
void finfact(int u){
st[u]--;
for(auto i:v[u]){
finfact(i);
}
return;
}
int res=0;
void dfs(int u,vector<int>&ve,int now){
bool bl=false;
_rep(i,1,n){
if(st[i])continue;
bl=true;
sum=0;
infact(i);
dfs(u+1,ve,now*qmi(c[u],sum,P)%P);
finfact(i);
}
if(!bl)res+=now,res%=P;
}
void solve(){
cin>>n;
_rep(i,2,n){
int x;
cin>>x;
v[x].pb(i);
}
_rep(i,1,n)cin>>c[i];
vector<int>ve;
dfs(1,ve,1);
cout<<res;
}
signed main(){
IOS;
int T=1;
while(T--)
solve();
return 0;
}

