CF Round #542 (Div. 2)

ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目链接:https://codeforces.com/contest/1130

B
贪心,看看下一步在两个中选哪一个
题目:
蛋糕是1,2,3,4...升序排序的。
有两个人叠蛋糕,求路途的最小。
---------------------------------
那么也就是说我们要考虑的是下一步谁走哪个数的问题,当一个人确定走哪个数后,
另一个人也确定了走哪个数。
显然,假设走到了第i个数,无论哪个人走了哪个i,之后的最小路途都是固定的。
也就是说,我们需要考虑的是i-1走到i的过程。
也符合了无后效应。
所以对于每一步选择有:a1,a2指的是两个i-1,b1,b2是两个i 
min(dis(a1,b1)+dis(a2,b2), dis(a1,b2)+dis(a2,b1)) 
#include<bits/stdc++.h>
#define ll long long 
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int a[100005],b[100005],n;
int main(){
	cin>>n;
	ll x,ans=0;
	fo(i,1,2*n){
		cin>>x;
		if(a[x])b[x]=i;
		else a[x]=i;
	}
	a[0]=b[0]=1;
	fo(i,1,n){
		ans += min(abs(a[i]-a[i-1])+abs(b[i]-b[i-1]), abs(a[i]-b[i-1])+abs(b[i]-a[i-1]));
	}
	cout<<ans;
}

B 排序解

#include<bits/stdc++.h>
#define ll long long 
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
struct node{
	int val,idx;
	bool operator<(const node &p)const{
		if(val==p.val)return idx<p.idx;
		else return val < p.val;
	}
}a[200005]; 
int n;
int main(){
	cin>>n;
	fo(i,1,2*n){
		cin>>a[i].val;
		a[i].idx = i;
	}
	sort(a+1,a+1+2*n);
	ll ans = 0;
	int last = 1, last2=1;
	fo(i,1,2*n){
		if(i&1){
			ans += abs(a[i].idx - last); // 小的和小的 
			last = a[i].idx;
		}else{
			ans += abs(a[i].idx - last2); // 大的和大的 
			last2 = a[i].idx;
		}
	}
	cout<<ans;
}
C
两块陆地,中间河流,求连起来的最小距离
------------------------------------- 
两遍BFS遍历两块陆地,枚举任意点的连接 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int N=55;
const int dx[] = {0,0,-1,1};
const int dy[] = {-1,1,0,0};
int n;
char a[N][N];
bool v[2][N][N];
vector<pair<int, int> > ANS[2];
void bfs(int s1, int c1, int type){
	queue<pair<int, int> >q;
	q.push({s1,c1});
	while(q.size()){
		int x = q.front().first;
		int y = q.front().second;
		q.pop();
		if(v[type][x][y])continue;
		v[type][x][y]=1;
		fo(i,0,3){
			int nowx = x+dx[i];
			int nowy = y+dy[i];
			if(nowx>=1 && nowx<=n && nowy>=1&&nowy<=n && !v[type][nowx][nowy] && a[nowx][nowy]=='0'){
				q.push({nowx,nowy});
			}
			if(nowx>=1 && nowx<=n && nowy>=1&&nowy<=n && !v[type][nowx][nowy] && a[nowx][nowy]=='1'){
				ANS[type].push_back({x,y});
			}
		}
	}
}
int main(){
	int s1,c1,s2,c2;
	cin>>n>>s1>>c1>>s2>>c2;
	getchar();
	fo(i,1,n){
		scanf("%s",a[i]+1);
	}
	bfs(s1,c1,0);
	bfs(s2,c2,1);
	int ans = 999999999;
	for(pair<int,int> p1 : ANS[0]){ // 河岸1 
		for(auto p2 : ANS[1]){ // 河岸2 
			ans = min(ans, (p1.first-p2.first)*(p1.first-p2.first)+
			(p1.second-p2.second)*(p1.second-p2.second));
		}
	}
	if(ans ==999999999) ans=0;
	cout<<ans;
	return 0;
}
D1 && D2 贪心
题目:
一趟火车从1走到n再到1,走圈
输入a,b表示a站有糖果,要运到b站,a!=b
火车容量无限,但是每次离开一个站只能带走一个糖果
现在输出n行
表示火车从各个站出发,运完所有糖果需要的时间
-------------------------------------------------
假设在第i个站有cnt[i]个糖果,
那么我们需要从i出发,走cnt[i]-1圈,然后回到i
再从i出发运到最后一个站,(因为每次只能带1个糖果)
dist(x,y) 表示从x到y的距离,mi[i]表示i运到其他站的最小的一次花费 
那么i运出的最小花费为 cost[i] = dist(起点,i) + (cnt[i]-1)*n + mi[i] 
现在要求从各个点出发运完全部糖果的最小花费
因为火车可以无限携带糖果
所以我们再运送花费时间最多的那个站的时候,顺路把其他站要运的也带上运完
ans = max(cost[i]) 
#include<bits/stdc++.h>
#define ll long long 
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int N=5050;
int n,m,cnt[N],mi[N];
int dist(int x, int y){
	if(y>=x)return y-x; // >=! 
	else return n-(x-y); 
}
int main(){
	scanf("%d%d",&n,&m);
	int x,y;
	memset(mi, 127, sizeof(mi)); 
	fo(i,1,m){
		scanf("%d%d",&x,&y); // x有糖果,要运到y
		cnt[x]++;
		mi[x] =  min(mi[x], dist(x,y));
	}
	// 因为火车可以放无限的糖果
	// 在每一个站可以多带走一个糖果
	// 所以在运送最长的那一趟糖果的同时,带上其他趟
	fo(i,1,n){ // 起点 
		ll ans = -1;
		fo(j,1,n){ // 枚举每个站 
			if(cnt[j]==0)continue;
			// 每个站的最短运输时间取最大即为该起点i需要的总运输时间 
			ans = max(ans, (ll)n*(cnt[j]-1) + dist(i,j) + mi[j]); 
		}
		printf("%lld ",ans); 
	} 
	return 0;
}
E
求max(sum(R-L+1)*a[i])  0<=L<=R<n, L<=i<=R
Alice写了个错误的算法,类似 连续最大子段和吧
现在知道正确答案和Alice的答案差k
求数列
-------------------------------------------
假设 a[0] = -1, a[i]>=1,那么sum(a) = S
Alice 的答案为  (n-1)*(S+1)  除了第一个数
可能的答案为 S*n 或Aliice的答案
假设正确答案为 S*n
那么 S*n - (n-1)*(S+1) = k
即 S - n + 1 = k
我们可以令 n = 2000 构造数组 
#include<bits/stdc++.h> 
using namespace std;
long long k,S,a[2006];
int main(){
	// S*n - (n-1)*(S+1) = k
	cin>>k; // S - n + 1 = k
	long long n = 2000;
	S = k+n-1;
	a[0] = -1;
	for(int i=2;i<n;i++)a[i]=1;
	a[1] = S-a[0]-(n-2); //其他都为1
	cout<<n<<endl;
	int i=2;
	// 不超过1e6 
	while(a[1]>1000000){
		a[i++]+=1000000-1;
		a[1]-=1000000-1;
	}
	for(int i=0; i<n; i++){
		cout<<a[i]<<" ";
	} 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值