CODEFORCES ROUND #642 (DIV. 3)[蒟蒻讲解]

http://www.yyycode.cn/index.php/2020/05/16/codeforces-round-642-div-3/


A. Most Unstable Array

You are given two integers nn and mm. You have to construct the array aa of length nn consisting of non-negative integers (i.e. integers greater than or equal to zero) such that the sum of elements of this array is exactly mm and the value ∑i=1n−1|ai−ai+1|∑i=1n−1|ai−ai+1| is the maximum possible. Recall that |x||x| is the absolute value of xx.

In other words, you have to maximize the sum of absolute differences between adjacent (consecutive) elements. For example, if the array a=[1,3,2,5,5,0]a=[1,3,2,5,5,0] then the value above for this array is |1−3|+|3−2|+|2−5|+|5−5|+|5−0|=2+1+3+0+5=11|1−3|+|3−2|+|2−5|+|5−5|+|5−0|=2+1+3+0+5=11. Note that this example doesn’t show the optimal answer but it shows how the required value for some array is calculated.

You have to answer tt independent test cases.Input

The first line of the input contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases. Then tt test cases follow.

The only line of the test case contains two integers nn and mm (1≤n,m≤1091≤n,m≤109) — the length of the array and its sum correspondingly.Output

For each test case, print the answer — the maximum possible value of ∑i=1n−1|ai−ai+1|∑i=1n−1|ai−ai+1| for the array aa consisting of nn non-negative integers with the sum mm.ExampleinputCopy

5
1 100
2 2
5 5
2 1000000000
1000000000 1000000000

outputCopy

0
2
10
1000000000
2000000000

Note

In the first test case of the example, the only possible array is [100][100] and the answer is obviously 00.

In the second test case of the example, one of the possible arrays is [2,0][2,0] and the answer is |2−0|=2|2−0|=2.

In the third test case of the example, one of the possible arrays is [0,2,0,3,0][0,2,0,3,0] and the answer is |0−2|+|2−0|+|0−3|+|3−0|=10|0−2|+|2−0|+|0−3|+|3−0|=10.


题意:在一条长为n的数轴上放总和的m的几个数字,问使得 |相邻数字之差|的总和最大

刚碰到的时候看了样例第一眼是猜乘2,但是不知道对不对,自己再进行简单的构造举例子之后写下去.

就以题目的样例为例子,n=6,m=16:

0 0 0 0 0 0

0 8 0 8 0 0 这样子来说每个8获得的两个邻边的和是最大的,如果分一个小数字在最后一个,0 8 0 7 0 1,最后那个1只有左边的有加,对于原来的来说有亏损


反思:对于这种构造题,一定要大胆猜测,用比较特殊的例子去构造猜测,打算去atcoder练习一波多总结


B. Two Arrays And Swaps

You are given two arrays aa and bb both consisting of nn positive (greater than zero) integers. You are also given an integer kk.

In one move, you can choose two indices ii and jj (1≤i,j≤n1≤i,j≤n) and swap aiai and bjbj (i.e. aiai becomes bjbj and vice versa). Note that ii and jj can be equal or different (in particular, swap a2a2 with b2b2 or swap a3a3 and b9b9 both are acceptable moves).

Your task is to find the maximum possible sum you can obtain in the array aa if you can do no more than (i.e. at most) kk such moves (swaps).

You have to answer tt independent test cases.Input

The first line of the input contains one integer tt (1≤t≤2001≤t≤200) — the number of test cases. Then tt test cases follow.

The first line of the test case contains two integers nn and kk (1≤n≤30;0≤k≤n1≤n≤30;0≤k≤n) — the number of elements in aa and bb and the maximum number of moves you can do. The second line of the test case contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤301≤ai≤30), where aiai is the ii-th element of aa. The third line of the test case contains nn integers b1,b2,…,bnb1,b2,…,bn (1≤bi≤301≤bi≤30), where bibi is the ii-th element of bb.Output

For each test case, print the answer — the maximum possible sum you can obtain in the array aa if you can do no more than (i.e. at most) kk swaps.ExampleinputCopy

5
2 1
1 2
3 4
5 5
5 5 6 6 5
1 2 5 4 3
5 3
1 2 3 4 5
10 9 10 10 9
4 0
2 2 4 3
2 4 2 3
4 4
1 2 2 1
4 4 5 4

outputCopy

6
27
39
11
17

Note

In the first test case of the example, you can swap a1=1a1=1 and b2=4b2=4, so a=[4,2]a=[4,2] and b=[3,1]b=[3,1].

In the second test case of the example, you don’t need to swap anything.

In the third test case of the example, you can swap a1=1a1=1 and b1=10b1=10, a3=3a3=3 and b3=10b3=10 and a2=2a2=2 and b4=10b4=10, so a=[10,10,10,4,5]a=[10,10,10,4,5] and b=[1,9,3,2,9]b=[1,9,3,2,9].

In the fourth test case of the example, you cannot swap anything.

In the fifth test case of the example, you can swap arrays aa and bb, so a=[4,4,5,4]a=[4,4,5,4] and b=[1,2,2,1]b=[1,2,2,1].


题意:把a[]中的较小数换成能使a[]的总和增大的数,在b【】中找替换。

思路:a按照从小到大排序,b按照从大到小排序,如果a[i]<b[i]就可以替换,最小的数字用最大的数字去换最贪心。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5;
typedef long long LL;
LL a[maxn];
LL b[maxn];
bool cmp(LL q,LL w)
{
	return q>w;
}
int main(void)
{
	LL t;cin>>t;
	while(t--)
	{
		LL n,k;cin>>n>>k;
		LL sum=0;
		for(LL i=1;i<=n;i++)
			cin>>a[i],sum+=a[i];
		sort(a+1,a+1+n);	
		for(LL i=1;i<=n;i++)
			cin>>b[i]; 
		sort(b+1,b+1+n,cmp);
		for(LL i=1;i<=k;i++)
		{
			if(a[i]<=b[i])
			{
				sum+=(b[i]-a[i]);
			}
		}
		cout<<sum<<endl;
	}

return 0;
}


C. Board Moves

You are given a board of size n×nn×n, where nn is odd (not divisible by 22). Initially, each cell of the board contains one figure.

In one move, you can select exactly one figure presented in some cell and move it to one of the cells sharing a side or a corner with the current cell, i.e. from the cell (i,j)(i,j) you can move the figure to cells:

  • (i−1,j−1)(i−1,j−1);
  • (i−1,j)(i−1,j);
  • (i−1,j+1)(i−1,j+1);
  • (i,j−1)(i,j−1);
  • (i,j+1)(i,j+1);
  • (i+1,j−1)(i+1,j−1);
  • (i+1,j)(i+1,j);
  • (i+1,j+1)(i+1,j+1);

Of course, you can not move figures to cells out of the board. It is allowed that after a move there will be several figures in one cell.

Your task is to find the minimum number of moves needed to get all the figures into one cell (i.e. n2−1n2−1 cells should contain 00 figures and one cell should contain n2n2 figures).

You have to answer tt independent test cases.Input

The first line of the input contains one integer tt (1≤t≤2001≤t≤200) — the number of test cases. Then tt test cases follow.

The only line of the test case contains one integer nn (1≤n<5⋅1051≤n<5⋅105) — the size of the board. It is guaranteed that nn is odd (not divisible by 22).

It is guaranteed that the sum of nn over all test cases does not exceed 5⋅1055⋅105 (∑n≤5⋅105∑n≤5⋅105).Output

For each test case print the answer — the minimum number of moves needed to get all the figures into one cell.ExampleinputCopy

3
1
5
499993

outputCopy

0
40
41664916690999888

题意:给一个nXn的矩阵,n是奇数,找一个地方使得所有的点到这个点的步数之和最小..

做的时候直觉是中心点,应该是能用不等式相关知识证明出来的.然后注意是八个方向.

做的时候以中心点为起点,然后每个格子里写上到中心点的距离,发现是一圈一圈的,比如n=5,中间是n=3的圈,最外面一圈都是n=2,发现规律即可

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5;
typedef long long LL;

int main(void)
{
	LL t;cin>>t;
	while(t--)
	{
		LL n;cin>>n;
		LL ans=0;
		LL g=n*n-1;
		LL temp=8;
		LL res=1;
		while(g>0)
		{
			ans+=temp*(res);
			g-=temp;
			temp+=8;
			res++;
		}
		cout<<ans<<endl;
	}

return 0;
}

D. Constructing the Array

You are given an array aa of length nn consisting of zeros. You perform nn actions with this array: during the ii-th action, the following sequence of operations appears:

  1. Choose the maximum by length subarray (continuous subsegment) consisting only of zeros, among all such segments choose the leftmost one;
  2. Let this segment be [l;r][l;r]. If r−l+1r−l+1 is odd (not divisible by 22) then assign (set) a[l+r2]:=ia[l+r2]:=i (where ii is the number of the current action), otherwise (if r−l+1r−l+1 is even) assign (set) a[l+r−12]:=ia[l+r−12]:=i.

Consider the array aa of length 55 (initially a=[0,0,0,0,0]a=[0,0,0,0,0]). Then it changes as follows:

  1. Firstly, we choose the segment [1;5][1;5] and assign a[3]:=1a[3]:=1, so aa becomes [0,0,1,0,0][0,0,1,0,0];
  2. then we choose the segment [1;2][1;2] and assign a[1]:=2a[1]:=2, so aa becomes [2,0,1,0,0][2,0,1,0,0];
  3. then we choose the segment [4;5][4;5] and assign a[4]:=3a[4]:=3, so aa becomes [2,0,1,3,0][2,0,1,3,0];
  4. then we choose the segment [2;2][2;2] and assign a[2]:=4a[2]:=4, so aa becomes [2,4,1,3,0][2,4,1,3,0];
  5. and at last we choose the segment [5;5][5;5] and assign a[5]:=5a[5]:=5, so aa becomes [2,4,1,3,5][2,4,1,3,5].

Your task is to find the array aa of length nn after performing all nn actions. Note that the answer exists and unique.

You have to answer tt independent test cases.Input

The first line of the input contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases. Then tt test cases follow.

The only line of the test case contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the length of aa.

It is guaranteed that the sum of nn over all test cases does not exceed 2⋅1052⋅105 (∑n≤2⋅105∑n≤2⋅105).Output

For each test case, print the answer — the array aa of length nn after performing nn actions described in the problem statement. Note that the answer exists and unique.ExampleinputCopy

6
1
2
3
4
5
6

outputCopy

1 
1 2 
2 1 3 
3 1 2 4 
2 4 1 3 5 
3 4 1 5 2 6 

题意:按照题目给的规则去构造数组,答案唯一。规则:找连续的空的序列,找出最长的,如果有同长,选左端点在最左边的那个,然后标记这是第几个找到的,最后输出。题目说了有且只有一个

自己做的时候是模拟,但是🐎力太差,并且知道单纯暴力模拟不行,然后看题,题目说了“如果一样长,找最左边的”&&“找一段最长的空的序列”,能快速维护同个类型并且直接返回最小的或者最大的数据结构是堆。于是用优先队列帮助模拟思考。优先队列无参数默认大根堆,我们重载成为小根堆满足找端点最左边的那个。

优先队列默认大根堆, 重载成小根堆 
struct Node
{
	LL len;LL l;LL r;
	//重载操作. 
	bool operator<(const struct Node &B)const{
		if(len==B.len) return l>B.l;///区间长度一样返回左边的 
		return len<B.len;//不然返回区间长度大的 
	}
};
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2e5+10;
typedef long long LL;
LL a[maxn];
优先队列默认大根堆, 重载成小根堆 
struct Node
{
	LL len;LL l;LL r;
	//重载操作. 
	bool operator<(const struct Node &B)const{
		if(len==B.len) return l>B.l;///区间长度一样返回左边的 
		return len<B.len;//不然返回区间长度大的 
	}
};
void solve(LL n,LL idx)
{
	priority_queue<Node>q;
	q.push({n,1,n});
	while(q.size())
	{
		Node t=q.top();q.pop();
		LL nowl=t.l;LL nowr=t.r;LL nowlen=t.len;
		LL mid=(nowl+nowr)>>1;
		a[mid]=++idx;
		if(mid-nowl>=1)
		q.push({mid-nowl,nowl,mid-1});
		if(nowr-mid>=1)
		q.push({nowr-mid, mid+1,nowr}); 
	}
		
}

int main(void)
{
	LL t;cin>>t;
	while(t--)
	{
		LL n;cin>>n;
		LL idx=0;
		solve(n,idx);
		for(int i=1;i<=n;i++)
			cout<<a[i]<<' ';
		cout<<endl;
	}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值