Codeforces Round #598 (Div. 3)

A. Payment Without Change

A. Payment Without Change
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You have a coins of value n and b coins of value 1. You always pay in exact change, so you want to know if there exist such x and y that if you take x (0≤x≤a) coins of value n and y (0≤y≤b) coins of value 1, then the total value of taken coins will be S.

You have to answer q independent test cases.

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

The only line of the test case contains four integers a, b, n and S (1≤a,b,n,S≤109) — the number of coins of value n, the number of coins of value 1, the value n and the required total value.

Output
For the i-th test case print the answer on it — YES (without quotes) if there exist such x and y that if you take x coins of value n and y coins of value 1, then the total value of taken coins will be S, and NO otherwise.

You may print every letter in any case you want (so, for example, the strings yEs, yes, Yes and YES will all be recognized as positive answer).

Example
inputCopy
4
1 2 3 4
1 2 3 6
5 2 6 27
3 3 5 18
outputCopy
YES
NO
NO
YES

题意:
给你一个数 s,还有a个数n,b个数1,能否找到x个n和y个1的和为s;
思路:
题意简单,但是直接暴力会超时;两种做法,
一:找规律
判断s最多能由几个n组成,剩下的余数必须小于b;

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		//cout <<t<<endl;
		ll a,b,n,s;
		scanf("%lld %lld %lld %lld",&a,&b,&n,&s);
		if(a*n+b<s) 
		{
			printf("NO\n");
			continue;
		}
		ll cot=min(s/n,a);
		if(s-cot*n<=b) printf("YES\n");
		else printf("NO\n");
	} 
	return 0;
} 

二: 用二分查找x的值,虽说也是暴力,但是比起直接循环暴力要省很多时间;

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
	//std::ios::sync_with_stdio(false);
	ll n,a,b,s;
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int flag=false;
		scanf("%lld %lld %lld %lld",&a,&b,&n,&s);
		ll l=0,r=a,mid;
		while(l<r)
		{
			mid=l+r>>1;
			if(s-mid*n<=b&&mid*n<=s)
			{
				l=mid;
				break;
			} 
			if(mid*n>s) r=mid; 
			else l=mid+1;
		}
		//cout <<r<<endl;
		if(s-l*n<=b&&l*n<=s) printf("YES\n");
		else printf("NO\n");
	}
}

.

B. Minimize the Permutation

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a permutation of length n. Recall that the permutation is an array consisting of n distinct integers from 1 to n in arbitrary order. For example, [2,3,1,5,4] is a permutation, but [1,2,2] is not a permutation (2 appears twice in the array) and [1,3,4] is also not a permutation (n=3 but there is 4 in the array).

You can perform at most n−1 operations with the given permutation (it is possible that you don’t perform any operations at all). The i-th operation allows you to swap elements of the given permutation on positions i and i+1. Each operation can be performed at most once. The operations can be performed in arbitrary order.

Your task is to find the lexicographically minimum possible permutation obtained by performing some of the given operations in some order.

You can see the definition of the lexicographical order in the notes section.

You have to answer q independent test cases.

For example, let’s consider the permutation [5,4,1,3,2]. The minimum possible permutation we can obtain is [1,5,2,4,3] and we can do it in the following way:

perform the second operation (swap the second and the third elements) and obtain the permutation [5,1,4,3,2];
perform the fourth operation (swap the fourth and the fifth elements) and obtain the permutation [5,1,4,2,3];
perform the third operation (swap the third and the fourth elements) and obtain the permutation [5,1,2,4,3].
perform the first operation (swap the first and the second elements) and obtain the permutation [1,5,2,4,3];
Another example is [1,2,4,3]. The minimum possible permutation we can obtain is [1,2,3,4] by performing the third operation (swap the third and the fourth elements).

Input
The first line of the input contains one integer q (1≤q≤100) — the number of test cases. Then q test cases follow.

The first line of the test case contains one integer n (1≤n≤100) — the number of elements in the permutation.

The second line of the test case contains n distinct integers from 1 to n — the given permutation.

Output
For each test case, print the answer on it — the lexicograhically minimum possible permutation obtained by performing some of the given operations in some order.

Example
inputCopy
4
5
5 4 1 3 2
4
1 2 4 3
1
1
4
4 3 2 1
outputCopy
1 5 2 4 3
1 2 3 4
1
1 4 3 2
Note
Recall that the permutation p of length n is lexicographically less than the permutation q of length n if there is such index i≤n that for all j from 1 to i−1 the condition pj=qj is satisfied, and pi<qi. For example:

p=[1,3,5,2,4] is less than q=[1,3,5,4,2] (such i=4 exists, that pi<qi and for each j<i holds pj=qj),
p=[1,2] is less than q=[2,1] (such i=1 exists, that pi<qi and for each j<i holds pj=qj).

题意:
题意读懂很关键,给你一串长为n的数字,现在你可以进行n-1次操作,规定如下,当你进行第i次操作的时候,你可以移动交换a[i] 和 a[i+1]的值;操作执行顺序是任意的;找出来n-1次执行之后数字的最小字典顺序;

思路:
贪心的思想,从1—n,依次把小的数往前挪动,并且操作过的命令被标记,不能再操作;模拟整个过程,注意细节;如果挪动过程中前面的数比当前数小,停止挪动;

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
map<int,int> mp;//存放某个数的位置
int a[1001];
map<int,int> mpp;//标记某个操作是否执行过
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		mp.clear();
		mpp.clear();
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),mp[a[i]]=i,mpp[i]=1;
		int cot=n-1;
		for(int i=1;i<=n;i++)
		{
			int x=mp[i];
			for(int j=x;j>=2;j--)
			{
				if(a[j]>a[j-1] ) continue;
				if(!mpp[j-1]) break;
				mp[a[j]]=j-1,mp[a[j-1]]=j;
				mpp[j-1]=0;
				swap(a[j],a[j-1]);
				cot--;
				if(cot<=0) break;
			}
			if(cot<=0) break;
		}
		for(int i=1;i<=n;i++) printf("%d ",a[i]);
		printf("\n");
	} 
} 

.

C. Platforms Jumping

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
There is a river of width n. The left bank of the river is cell 0 and the right bank is cell n+1 (more formally, the river can be represented as a sequence of n+2 cells numbered from 0 to n+1). There are also m wooden platforms on a river, the i-th platform has length ci (so the i-th platform takes ci consecutive cells of the river). It is guaranteed that the sum of lengths of platforms does not exceed n.

You are standing at 0 and want to reach n+1 somehow. If you are standing at the position x, you can jump to any position in the range [x+1;x+d]. However you don’t really like the water so you can jump only to such cells that belong to some wooden platform. For example, if d=1, you can jump only to the next position (if it belongs to the wooden platform). You can assume that cells 0 and n+1 belong to wooden platforms.

You want to know if it is possible to reach n+1 from 0 if you can move any platform to the left or to the right arbitrary number of times (possibly, zero) as long as they do not intersect each other (but two platforms can touch each other). It also means that you cannot change the relative order of platforms.

Note that you should move platforms until you start jumping (in other words, you first move the platforms and then start jumping).

For example, if n=7, m=3, d=2 and c=[1,2,1], then one of the ways to reach 8 from 0 is follow:

The first example: n=7.
Input
The first line of the input contains three integers n, m and d (1≤n,m,d≤1000,m≤n) — the width of the river, the number of platforms and the maximum distance of your jump, correspondingly.

The second line of the input contains m integers c1,c2,…,cm (1≤ci≤n,∑i=1mci≤n), where ci is the length of the i-th platform.

Output
If it is impossible to reach n+1 from 0, print NO in the first line. Otherwise, print YES in the first line and the array a of length n in the second line — the sequence of river cells (excluding cell 0 and cell n+1).

If the cell i does not belong to any platform, ai should be 0. Otherwise, it should be equal to the index of the platform (1-indexed, platforms are numbered from 1 to m in order of input) to which the cell i belongs.

Note that all ai equal to 1 should form a contiguous subsegment of the array a of length c1, all ai equal to 2 should form a contiguous subsegment of the array a of length c2, …, all ai equal to m should form a contiguous subsegment of the array a of length cm. The leftmost position of 2 in a should be greater than the rightmost position of 1, the leftmost position of 3 in a should be greater than the rightmost position of 2, …, the leftmost position of m in a should be greater than the rightmost position of m−1.

See example outputs for better understanding.

Examples
inputCopy
7 3 2
1 2 1
outputCopy
YES
0 1 0 2 2 0 3
inputCopy
10 1 11
1
outputCopy
YES
0 0 0 0 0 0 0 0 0 1
inputCopy
10 1 5
2
outputCopy
YES
0 0 0 0 1 1 0 0 0 0
Note
Consider the first example: the answer is [0,1,0,2,2,0,3]. The sequence of jumps you perform is 0→2→4→5→7→8.

Consider the second example: it does not matter how to place the platform because you always can jump from 0 to 11.

Consider the third example: the answer is [0,0,0,0,1,1,0,0,0,0]. The sequence of jumps you perform is 0→5→6→11.

题意:
长度为n的河,有m个木板飘在河面上,让你过河;给你每次能跳的最远距离是多少,然后事先让你左右移动木板(但是不能改变木板的相对顺序)所有木板都要用上;问你能否有一种方案可以过河,并且输出每次落脚点的所在木板的下标;

思路:
一道思维模拟题,细节很多;首先如果有m个木板,那么能跳m+1次,也就是说,总共能跨过的和的长度为cot=(m+1)*(d-1);如果cot<(河的宽度减去木板的总长度),那么就不能成功到达对岸;反之亦然;然后模拟整个跳的过程,需要注意的细节在代码中给出;

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int c[100010];
int a[100010];
int main()
{
	int n,m,d;
	scanf("%d %d %d",&n,&m,&d);
	int sum=0;
	for(int i=1;i<=m;i++) scanf("%d",&c[i]),sum+=c[i];//求出木板总长度
	int cot=m+1,flag=0,sub=n-sum;//河长度与木板长度的差值
	//cout <<sub<<endl;
	if(cot*(d-1)>=sub) flag=1,printf("YES\n");
	else printf("NO\n");
	if(flag)
	{
		cot=0;//最初跳过的河的长度;
		int ff=0;
		for(int i=1;i<=m;i++)
		{
			if(cot>n) break;
			int j=1;
			while(j<=d-1&&j<=sub&&cot<=n&&!ff)//跳的距离不能超过d-1并且不能超过此时剩下的河与木板长度的差值;
			{
				printf("0 "),j++,cot++;
				if(n-cot==sum)//如果剩下的河的长度等于剩下的木板的长度,那么接下来就一直走在木板上;
				{
					ff=1;
					break;
				}
			 } 
			j=1,sub-=j-1;
			while(j<=c[i]&&cot<=n) printf("%d ",i),j++,cot++,sum--;//在木板上时;
			
		}
		while(cot<n)//如果所有的木板都最大化利用完了,那么剩下的就直接跳过去,跳到对岸;
		{
			printf("0 ");
			cot++;
		}
		//cout <<cot<<endl;
	}
	return 0;
} 

.

D. Binary String Minimizing

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a binary string of length n (i. e. a string consisting of n characters ‘0’ and ‘1’).

In one move you can swap two adjacent characters of the string. What is the lexicographically minimum possible string you can obtain from the given one if you can perform no more than k moves? It is possible that you do not perform any moves at all.

Note that you can swap the same pair of adjacent characters with indices i and i+1 arbitrary (possibly, zero) number of times. Each such swap is considered a separate move.

You have to answer q independent test cases.

Input
The first line of the input contains one integer q (1≤q≤104) — the number of test cases.

The first line of the test case contains two integers n and k (1≤n≤106,1≤k≤n2) — the length of the string and the number of moves you can perform.

The second line of the test case contains one string consisting of n characters ‘0’ and ‘1’.

It is guaranteed that the sum of n over all test cases does not exceed 106 (∑n≤106).

Output
For each test case, print the answer on it: the lexicographically minimum possible string of length n you can obtain from the given one if you can perform no more than k moves.

Example
inputCopy
3
8 5
11011010
7 9
1111100
7 11
1111100
outputCopy
01011110
0101111
0011111
Note
In the first example, you can change the string as follows: 110–––11010→10–––111010→011110–––10→01110–––110→0110–––1110→01011110.

In the third example, there are enough operations to make the string sorted.

题意:
长度为n的二进制字符串;给你k个操作;然后让你移动数字,每次只能移动相邻的两个数字;求k次之后能得到的字典序最小的字符串为多少(操作数可能小于k);
思路:
如果直接暴力需要注意两个地方:k的范围1e12;当0往前移动时,如果前面都是0,那么就不再进行移动; 暴力只要注意这两个问题,就ok,但会超时,无奈,k太大了;所以对于0,只需要寻找它最多能往前移动到哪个位置即可(与距离它最远的前面的1互换位置);

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    int q;
    cin >> q;
    while (q--) {
        int n;
        long long k;
        cin >> n >> k;
        string s;
        cin >> s;
        int j=0;
        for(int i=0;i<n;i++)
        {
        	if(j<i) j=i;//如果是连续的1,就一直往右;
        	while(j<n&&s[j]!='0') j++;//找到距离此时这个1最远的右边的0
        	if(j<n&&j-i<=k)//如果这个0和前面最远的1之间位置差小于操作数的值,那么互换位置;
        	{
        		k-=j-i;
        		swap(s[i],s[j]);
			}
			if(k==0) break;
		}
		cout <<s<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值