【比赛】暑假集训CSP提高模拟2

T1 活动投票 0Pts
摩尔投票板子。
这题卡了不加速的 cin 导致我一分没拿。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,x,now,cnt;
int main(){
ios::sync_with_stdio(0);
cin>>n;
while(n--){
cin>>x;
if(!cnt)now=x;
if(x==now)cnt++;
else cnt--;
}
cout<<now;
return 0;
}
T2 序列 10Pts
原题 不无聊的序列 Non-boring sequences
如果暴力枚举子串的话,复杂度为 \(O(n^4)\),且“枚举子串”的 \(n^2\) 显然无法优化;
所以改变思路,考虑每个点;
我们记录一下一个数上一次出现的位置和下一次出现的位置,这样可以判断在 \(l\) 到 \(r\) 中一个数是否仅出现一次;
如果该序列不无聊,那么对于任意一个序列 \([l,r]\),都有一个 \(a_k\) 是唯一存在的数,那么在 \([l,r]\) 中包含该数的序列都不无聊,递归求解 \([l,k-1]\) 和 \([k+1,r]\) 即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int T,n;
int a[N],pre[N],nxt[N];
map<int,int> mp;
bool solve(int L,int R){
if(L>=R)return 1;
int l=L,r=R;
while(l<=r){
if(pre[l]<L&&nxt[l]>R)return solve(L,l-1)&&solve(l+1,R);
if(pre[r]<L&&nxt[r]>R)return solve(L,r-1)&&solve(r+1,R);
l++;r--;
}
return 0;
}
int main(){
cin>>T;
while(T--){
mp.clear();
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
nxt[i]=n+1;
pre[i]=mp[a[i]],nxt[pre[i]]=i;
mp[a[i]]=i;
}
cout<<(solve(1,n)?"non-boring":"boring")<<"\n";
}
return 0;
}
T3 Legacy 40Pts
原题 Legacy
线段树优化建图板子。
暴力建图的时空都严重不对,所以我们要线段树优化建图。
开两颗线段树,一颗记录入边,一颗记录出边,相同点之间连权值为 \(0\) 的边,随后直接连边跑就行。
点击查看代码
#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=3e6+5;
const int K=5e5;
int n,m,s,op,x,y,z,l,r,w,a[N],dis[N],vis[N];
struct edge{
int next,to,w;
}e[N];
int h[N],cnt;
void add(int u,int v,int w){
e[++cnt]={h[u],v,w};
h[u]=cnt;
}
void build(int p,int l,int r){
if(l==r){
a[l]=p;
return;
}
int mid=(l+r)>>1;
add(p,p<<1,0);add(p,p<<1|1,0);
add((p<<1)+K,p+K,0);add((p<<1|1)+K,p+K,0);
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void update(int p,int l,int r,int L,int R,int v,int w,int op){
if(L<=l&&r<=R){
if(op==2)add(v+K,p,w);
else add(p+K,v,w);
return;
}
int mid=(l+r)>>1;
if(L<=mid)update(p<<1,l,mid,L,R,v,w,op);
if(R>mid)update(p<<1|1,mid+1,r,L,R,v,w,op);
}
void dij(int s){
priority_queue<pii> q;
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push({0,s});
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=h[u];i;i=e[i].next){
int to=e[i].to;
if(dis[to]>dis[u]+e[i].w){
dis[to]=dis[u]+e[i].w;
q.push({-dis[to],to});
}
}
}
}
main(){
cin>>n>>m>>s;
build(1,1,n);
for(int i=1;i<=n;i++){
add(a[i],a[i]+K,0);
add(a[i]+K,a[i],0);
}
for(int i=1;i<=m;i++){
cin>>op;
if(op==1){
cin>>x>>y>>z;
add(a[x]+K,a[y],z);
}
else{
cin>>x>>l>>r>>w;
update(1,1,n,l,r,a[x],w,op);
}
}
dij(a[s]+K);
for(int i=1;i<=n;i++){
if(dis[a[i]]==0x3f3f3f3f3f3f3f3f)dis[a[i]]=-1;
cout<<dis[a[i]]<<" ";
}
return 0;
}
T4 DP搬运工1 26Pts
题面

听得不是很懂,搬一下 @HaneDaniko 的题解:

膜拜了。
点击查看代码
#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
const int N=55;
const int mod=998244353;
int f[N][N][N*N];
int n,K;
main(){
cin>>n>>K;
f[1][0][0]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=n-i+1;j++){
for(int k=0;k<=K;k++){
if(!f[i-1][j][k])continue;
if(j){
f[i][j][k+i]=(f[i][j][k+i]+f[i-1][j][k]*2%mod*j%mod)%mod;
f[i][j+1][k]=(f[i][j+1][k]+f[i-1][j][k]*j%mod)%mod;
f[i][j-1][k+2*i]=(f[i][j-1][k+2*i]+f[i-1][j][k]*j%mod)%mod;
}
f[i][j][k+i]=(f[i][j][k+i]+f[i-1][j][k]*2%mod)%mod;
f[i][j+1][k]=(f[i][j+1][k]+f[i-1][j][k]*2%mod)%mod;
}
}
}
int ans=0;
for(int i=0;i<=K;i++){
ans=(ans+f[n][0][i])%mod;
}
cout<<ans;
return 0;
}