Codeforces Round #642 (Div. 3)(A-D题解)

A - Most Unstable Array (分类讨论)
题目大意:构造一个长度为n的数组.使元素和为m.最大化|a[i]-a[i+1]|.
长度大于3的时候就是2*m 因为可以这么去构造:
长度为3
0 a1 0
长度为4
0 a1 0 0
这样子肯定是最大的.把a1拆开来不可能会更大.
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int t,n,m;
int main(){
	cin >> t;
	while(t--){
		cin >> n >> m;
		if(n >= 3) cout << m*2 << endl;
		else{
			if(n == 2) cout << m << endl;
			else cout << 0 << endl;
		}
	}
	
	return 0;
}	

B - Two Arrays And Swaps (排序)
题目大意:给a,b两个数组.最多在B里面用k个数替换a里面的数.构造a数组最大和.
先排个序.然后b里面从最大值开始扫描,替换掉a里面的最小值.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int t,n;
int a[N],b[N];
int main(){
	cin >> t;
	while(t--){
		int k;
		cin >> n >> k;
		fir(i,1,n) cin >> a[i];
		fir(i,1,n) cin >> b[i];
		sort(a+1,a+1+n);
		sort(b+1,b+1+n);
		int j =1;
		int sum = 0;
		afir(i,n,1){
			if(k && b[i] > a[j]){
				k--;
				sum += b[i];
				j++;
			}
		}
		fir(i,j,n){
			sum += a[i];
		}
		cout <<sum << endl;
	}
	
	return 0;
}

C - Board Moves(找规律)
题目大意:给一个n*n(n为奇数)的矩阵.每个矩阵上都有一个元素.问把所有元素聚到一个格子里最小的代价(可以往八个方向移动).
计数题. 我们把所有元素都移动到中间的格子上.那每个元素的移动代价就是里中间元素x轴方向上的距离和y轴方向上距离比较大的一个.(因为可以斜着移动). 所以我们可以一圈一圈的从外往里算.
比如 n = 5.
最外面一圈的个数是5×5-3×3移动代价是2. 然后下一圈个数就是3×3-1×1移动代价是1.
代价一开始是(n-1)/2.然后每次减1. n每次-2.
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int t;
LL n;
int main(){
	cin >> t;
	while(t--){
		cin >> n;
		LL ans = 0;
		for(int i=(n-1)/2,j=n;i>=1;--i,j-=2){
			ans += (1LL*4*(j-1))*i;
		}
		cout << ans << endl;
	}
	
	return 0;
}	

D - Constructing the Array(模拟)
题目大意:给一个初始全部为0的长度为n的数组.从1开始放数. 放数的方式:每次找最长连续为0的子段,然后放到中间(向下取整的中间).最后输出放数结束后的数组.
优先级队列模板题.存l,r.为方便再存一个v是区间长度.按v排序,v相等按l排序.每次取最小的v出来后放完分割成为两个区间,找题意模拟就好了.
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int a[N];
struct Node{
	int l,r,v;
	bool operator<(const Node& w)const {
		if(v == w.v) return l > w.l;
		return v < w.v;
	}
};
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		Node sta;
		sta = {1,n,n};
		pq <Node> q;
		q.push(sta);
		int cnt = 1;
		while(q.size()){
			Node cur = q.top();
			q.pop();
			if(cur.l > cur.r) continue;
			int mid = cur.l+cur.r >> 1;
			a[mid] = cnt++;
			Node n1 = {cur.l,mid-1,(cur.v-1)/2};
			Node n2 = {mid+1,cur.r,cur.v/2};
			q.push(n1);
			q.push(n2);
		}
		fir(i,1,n) cout << a[i]<< " ";
		cout << endl;
	}
	
	return 0;
}

E - K-periodic Garland
有点想法但是没写出来…枚举最小循环节里面每个数的起始和末尾应该可以算出来.昨晚有点神志不清了,现在有点不想写,以后再来补这题吧.

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/106137324