2024牛客暑期多校训练营第一场题目解析与实现
题目C:动态维护序列权值
通过观察发现,每个元素a[i]在序列中经过多次操作后的权重为a[i]*i。当执行删除尾节点操作时,需从总和中减去该元素的权重;添加新元素时则将其权重累加至总和。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6+10;
ll a[MAXN];
void solve(){
int q;cin>q;
int cnt=0;ll total=0;
while(q--){
int t,v;cin>t>v;
while(t--&&cnt>0){
total -= a[cnt]*cnt;
cnt--;
}
a[++cnt]=v;
total += v*cnt;
cout<(total%1000000007)<'\n';
}
}
int main(){ios::sync_with_stdio(false);solve();}
题目H:双赛制排名计算
需分别计算队伍在两场比赛中的最优排名。通过二分查找确定基准排名后,排除具有双参赛资格的队伍干扰,最终取两场排名的最小值。
#include<bits/stdc++.h>
using namespace std;
struct Team{string name;ll score,time;};
bool cmp(Team a,Team b){return a.score!=b.score?a.score>b.score:a.time<b.time;}
void solve(){
int n,m;cin>n>m;
mapcount;
Team A[n+1],B[m+1];
for(int i=1;i<=n;i++)cin>A[i].name>A[i].score>A[i].time;
for(int i=1;i<=m;i++)cin>B[i].name>B[i].score>B[i].time;
sort(A+1,A+n+1,cmp);
sort(B+1,B+m+1,cmp);
// 二分查找逻辑省略
}
题目A:子序列位运算统计
采用组合数学方法计算满足条件的序列数量。通过预处理组合数表,结合快速幂运算,最终得到结果。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
int C[6000][6000];
void precompute(){
for(int i=0;i<6000;i++)C[i][0]=1;
for(int i=1;i<6000;i++)
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
}
void solve(){
int n,m,q;cin>n>m>q;
precompute();
int ans=0;
for(int i=1;i<=n;i++){
int val=pow(2,i)-1;
val=(val%MOD+MOD)*pow(2,m-1,MOD)%MOD;
ans=(ans+val*C[n][i]%MOD)%MOD;
}
cout<ans<'\n';
}
题目I:光路追踪算法
利用深度优先搜索识别链式结构与环形结构。通过记录访问状态,区分不同路径类型并计算对应的镜面数量。
#include<bits/stdc.h>
using namespace std;
char grid[1010][1010];
int vis[1010][1010][4];
vector<tuple<int,int,int>> path;
void dfs(int x,int y,int dir){
if(x<1||x>1000||y<1||y>1000)return;
if(vis[x][y][dir])return;
path.push_back({x,y,dir});
vis[x][y][dir]=1;
// 根据网格字符进行方向转换逻辑
}
void solve(){
// 边界扫描与环形结构处理逻辑
}
题目B:特殊子序列排除
通过动态规划计算唯一合法子序列的数量,并从总方案数中扣除。核心在于构建二维DP数组,记录特殊位分配方案。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
int dp[5005][5005];
void precompute(){
for(int i=1;i<5005;i++)
for(int j=1;j<=i;j++)
dp[i][j]=(dp[i-1][j-1]+dp[i][j-1])*i%MOD;
}
void solve(){
int n,m,q;cin>n>m>q;
precompute();
int ans=0;
for(int i=2;i<=n;i++){
int val=...; // 计算逻辑
ans=(ans+val)%MOD;
}
cout<ans<'\n';
}
题目D:树状数组应用
针对模数特性设计位运算方案,使用树状数组维护前缀和。通过位拆分策略,将复杂度控制在可接受范围。
#include<bits/stdc++.h>
using namespace std;
const int MAX_BIT=21;
int tree[MAX_BIT+2];
void update(int idx,int val){...}
int query(int idx){...}
void solve(){
int q;cin>q;
while(q--){
int op,val;cin>op>val;
if(op==1)update(val,1);
else cout<query(val)<'\n';
}
}
