【比賽】暑假集訓CSP提高模擬2

萝卜甜了發表於2024-07-26

T1 活動投票 0Pts

原題 yyy loves Maths VI (mode)

摩爾投票板子。
這題卡了不加速的 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;
}

相關文章