[36](CSP 集训)CSP-S 模拟 6

忌数与齐诸公子驰逐模拟赛。孙子见其算法不甚相远,代码有上、中、下、辈。于是孙子谓田忌曰:“君弟模拟赛,臣能令君胜。”田忌信然之,与王及诸公子赌千金。

及临质,“孙子曰:‘今以君之暴力与彼上等代码,取君上等代码与彼中等代码,取君中等代码与彼暴力。’既驰三题毕,而田忌一不胜而再胜,卒得王千金。”

A.一般图最小匹配

赛时可反悔贪心打出来了,但是不是在前缀和上维护的,所以爆了

直接 DP,\(f_{i,j}\) 表示前 \(i\) 个选了 \(j\) 对(注意到永远有 \(j\le \lfloor\frac{i}{2}\rfloor\)),转移显然

\[f_{i,j}=\min(f_{i-1,j},f_{i-2,j-1}+cost(i-1,i)) \]

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define abs(x) ((x)>0?(x):-(x))
int n,m,ans;
int a[5001];
int f[5001][5001];
signed main(){
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	scanf("%lld %lld",&n,&m);
	memset(f,0x3f,sizeof f);
	for(int i=0;i<=n;++i) f[i][0]=0;
	for(int i=1;i<=n;++i){
		scanf("%lld",&a[i]);
	}
	sort(a+1,a+n+1);
	for(int i=2;i<=n;++i){
		for(int j=1;j<=m;++j){
			f[i][j]=min(f[i-1][j],f[i-2][j-1]+a[i]-a[i-1]);
		}
	}
	int ans=0x3f3f3f3f3f3f3f3f;
	for(int i=1;i<=n;++i){
		ans=min(ans,f[i][m]);
	}
	cout<<ans<<endl;
}
又到了赛时美丽代码时间
//smjb
//爱谁调谁调
//累了

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define abs(x) ((x)>0?(x):-(x))
int n,m,ans;
int a[5001];
//struct list{
//	int l,r;
//}l[5001];
bool vis[5001];
//struct node{
//	int left_node,right_node;
//	int val;
//	bool isfh;
//	bool operator <(const node &A)const{
//		if(val==A.val) return isfh<A.isfh;
//		return val>A.val;
//	}
//};
//priority_queue<node>q;
//vector<pair<int,int>>v;
struct node{
	int left,right;
	int val;
	int morecost;
	bool isfh;
	bool operator <(const node &A)const{
		if(val==A.val) return morecost>A.morecost;
		return val>A.val;
	}
};
priority_queue<node>q;
signed main(){
//	ofstream cth("CON");
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
//	freopen("data/v.in","r",stdin);
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
	scanf("%lld %lld",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%lld",&a[i]);
	}
	sort(a+1,a+n+1);
//	cout<<"/";
	for(int i=2;i<=n;++i){
		q.push({i-1,i,abs(a[i]-a[i-1]),abs(a[i]-a[i-1]),false});
	}
	int ansm=0;
	if(n==2*m){	
		for(int i=1;i<=n-1;i+=2){
			ansm+=abs(a[i]-a[i+1]);
		}
//		cth<<ansm<<endl;
		cout<<ansm<<endl;
		return 0;
	}
	int cnt=0;
//	cth<<"m== "<<m<<endl;
	while(!q.empty()){
//		cth<<"cnt"<<cnt<<endl;
		if(cnt==m) break;
		node u=q.top();q.pop();
		if(u.isfh){
			if(vis[u.left-1] or vis[u.right+1]) continue;
//			cth<<"fh "<<u.left<<" "<<u.right<<" "<<u.val<<endl;
			ans-=abs(a[u.left]-a[u.right]);
			ans+=abs(a[u.left-1]-a[u.left])+abs(a[u.right]-a[u.right+1]);
			vis[u.right+1]=true;
			vis[u.left-1]=true;
			cnt++;
		}
		else{
			if(vis[u.left] or vis[u.right]) continue;
//			cth<<u.left<<" "<<u.right<<endl;
			vis[u.left]=true;
			vis[u.right]=true;
			ans+=abs(a[u.left]-a[u.right]);
			if(u.left!=1 and u.right!=n) q.push({u.left,u.right,max(abs(a[u.left]-a[u.left-1]),abs(a[u.right]-a[u.right+1])),abs(a[u.left]-a[u.left-1])+abs(a[u.right]-a[u.right+1])-abs(a[u.right]-a[u.left]),true});
			cnt++;
		}
	}
//	cth<<"::: "<<m<<" "<<cnt<<endl;
	if(m!=cnt){
//		cth<<"in";
		int ans1=0,ans2=0;
		vector<int>ans_;
		for(int i=1;i<=n-1;i+=2){
			ans_.push_back(abs(a[i]-a[i+1]));
		}
		sort(ans_.begin(),ans_.end());
		for(int i=0;i<=m-1;++i){
			ans1+=ans_[i];
		}
		ans_.clear();
			for(int i=n;i>=2;i-=2){
			ans_.push_back(abs(a[i]-a[i-1]));
		}
		sort(ans_.begin(),ans_.end());
		for(int i=0;i<=m-1;++i){
			ans2+=ans_[i];
		}
		ans=min(ans1,ans2);
	}
//	cth<<ans<<endl;
	cout<<ans<<endl;
//	if(n==m*2)assert(ansm==ans);
//	l[1].r=2;l[n].l=n-1;
//	l[1].l=-1;l[n].r=-1;
//	for(int i=2;i<=n-1;++i){
//		l[i].l=i-1;l[i].r=i+1;
//		q.push({i-1,i,a[i]-a[i-1],false});
//	}
//	q.push({n-1,n,a[n]-a[n-1],false});
//	int cnt=0;
//	while(!q.empty()){
//		node u=q.top();q.pop();
//		if(vis[u.left_node] or vis[u.right_node]){
//			continue;
//		}
//		if(!u.isfh) v.push_back({u.left_node,u.right_node});
//		else{
//			
//		}
//		cth<<u.left_node<<" "<<u.right_node<<" "<<u.val+(u.isfh?a[u.right_node]-a[u.left_node]:0)<<endl;
//		ans+=u.val+(u.isfh?a[u.right_node]-a[u.left_node]:0);cnt++;
//		if(cnt==m) break;
//		vis[u.left_node]=true;
//		vis[u.right_node]=true;
//		if(l[u.left_node].l!=-1) l[l[u.left_node].l].r=l[u.right_node].r;
//		if(l[u.right_node].r!=-1) l[l[u.right_node].r].l=l[u.left_node].l;
//		if(l[u.left_node].l!=-1 and l[u.right_node].r!=-1){
//			cth<<"insert ["<<l[u.left_node].l<<" "<<l[u.right_node].r<<", "<<a[l[u.right_node].r]-a[l[u.left_node].l]<<"]"<<endl;
//			q.push({l[u.left_node].l,l[u.right_node].r,a[l[u.right_node].r]-a[l[u.left_node].l],false});
//			if(!u.isfh){
//				q.push({l[u.left_node].l,l[u.right_node].r,
//					abs(a[l[u.right_node].r]-a[u.right_node])+abs(a[u.left_node]-a[l[u.left_node].l])
//					-abs(a[u.right_node]-a[u.left_node])-abs(a[l[u.right_node].r]-a[l[u.left_node].l]),true});
//				cth<<"insert ["<<l[u.left_node].l<<" "<<l[u.right_node].r<<", fh "<<(a[l[u.right_node].r]-a[u.right_node])+abs(a[u.left_node]-a[l[u.left_node].l])-abs(a[u.right_node]-a[u.left_node])-abs(a[l[u.right_node].r]-a[l[u.left_node].l])<<"]"<<endl;
//			}
//		}
//	}
//	cout<<min(ans,ansm)<<endl;
}

B.重定向

啥玩意

从前往后贪心每一对数 \((i,i+1)\),注意到如果满足以下几点条件就可以直接选成被删的点(设 \(\min_i\) 为目前没填过的数字里最小的,这个东西可以用优先队列维护,首先找到哪些值没出现过,然后丢进小根堆,用了啥就 pop 出来)

  • \(a_i=0\),且存在 \(j\),使得 \(j\gt i\)\(a_j\lt \min_i\),则删掉 \(a_j\),这个 \(j\) 可以通过提前维护出后缀最小值来得到
  • 否则,若 \(a_{i+1}=0\),如果 \(a_i\gt \min_i\),则删掉 \(a_i\)
  • 否则,若 \(a_i\gt a_{i+1}\),删掉 \(a_i\)

知道删掉啥数以后就好做了,暴力填一遍就行了

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x;
	bool operator <(const node& A)const{
		return x>A.x;
	} 
};
priority_queue<node>q;
const int inf=1e9;
int t,n,a[200001],pos[200001],minn[200001];
bool cnt[200001];
int main(){
	freopen("repeat.in","r",stdin);
	freopen("repeat.out","w",stdout);
	cin>>t;
	while(t--){
		scanf("%d",&n);
		memset(cnt,0,sizeof cnt);
		while(!q.empty()) q.pop();
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
			cnt[a[i]]=1;
			pos[a[i]]=i;
		}
		minn[n+1]=inf;
		for(int i=n;i>=1;--i){
			minn[i]=minn[i+1];
			if(a[i]!=0) minn[i]=min(minn[i],a[i]);
		}
		for(int i=1;i<=n;++i){
			if(!cnt[i]){
				q.push({i});
			}
		}
		int _pos=n;
		for(int i=1;i<=n-1;++i){
			if(!a[i]){
				if(minn[i]>q.top().x){
					a[i]=q.top().x;
					q.pop();
				}
				else{
					a[i]=minn[i];
					_pos=pos[a[i]];
					break;
				}
				continue;
			}
			if(a[i+1]){
				if(a[i]>a[i+1]){
					_pos=i;
					q.push({a[i]});
					break;
				}
			}
			else{
				if(a[i]>q.top().x){
					_pos=i;
					q.push({a[i]});
					break;
				}
			}
		}
		for(int i=1;i<=n;++i){
			if(a[i] or i==_pos){
				continue;
			}
			a[i]=q.top().x;
			q.pop();
		}
		for(int i=1;i<=n;++i){
			if(i!=_pos) printf("%d ",a[i]);
		}
		putchar('\n');
	}
}
/*
2
7
3 0 4 0 1 0 2
6
1 3 4 5 2 6

3 1 4 5 6 2
1 3 4 2 6
*/
posted @ 2024-09-28 15:00  HaneDaniko  阅读(47)  评论(2编辑  收藏  举报