Codeforces Round #424 Div.2 A B C D E F

A. Unimodal Array
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Array of integers is unimodal, if:

  • it is strictly increasing in the beginning;
  • after that it is constant;
  • after that it is strictly decreasing.

The first block (increasing) and the last block (decreasing) may be absent. It is allowed that both of this blocks are absent.

For example, the following three arrays are unimodal: [5, 7, 11, 11, 2, 1][4, 4, 2][7], but the following three are not unimodal: [5, 5, 6, 6, 1][1, 2, 1, 2][4, 5, 5, 6].

Write a program that checks if an array is unimodal.

Input

The first line contains integer n (1 ≤ n ≤ 100) — the number of elements in the array.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1 000) — the elements of the array.

Output

Print "YES" if the given array is unimodal. Otherwise, print "NO".

You can output each letter in any case (upper or lower).

Examples
input
6
1 5 5 5 4 2
output
YES
input
5
10 20 30 20 10
output
YES
input
4
1 2 1 2
output
NO
input
7
3 3 3 3 3 3 3
output
YES
Note

In the first example the array is unimodal, because it is strictly increasing in the beginning (from position 1to position 2, inclusively), that it is constant (from position 2 to position 4, inclusively) and then it is strictly decreasing (from position 4 to position 6, inclusively).


A题一向是水题,比赛时候还是写挂了。。。

没认真读题,把1,2,3这样递增的数列也当做不合法了。

AC代码:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string.h>
#include <string> 
#include <map>
#include <algorithm>
#include <queue>
#include <math.h>
#include <cmath>
#define mem(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;

int main() {
	int n,i,x,flag=1,y;
	scanf("%d",&n);
	scanf("%d",&x);
	if (n==1) {
		cout << "YES";
		return 0;
	}
	int k=1005;
	for (i=2;i<=n;i++) {
		scanf("%d",&y);
		if (y<=x) {
			if (y==x) {
				flag=2;
				k=i;
				x=y;
				break;
			} else {
				flag=3;
				x=y;
				k=i;
				break;
				if (i==n) {
					cout << "NO";
					return 0;
				}
			}
		}
		x=y;
	}
	if (i==n+1) {
		cout << "Yes";
		return 0;
	}
	if (flag!=3)
	for (i=k+1;i<=n;i++) {
		scanf("%d",&y);
		if (y!=x) {
			if (y<x) {
				flag=3;
				k=i;
				x=y;
				break;
			} else {
				cout << "NO";
		        return 0;
			}
		}
		x=y;
	}
	if (i==n+1) {
		cout << "YES";
		return 0;
	}
	for (i=k+1;i<=n;i++) {
		scanf("%d",&y);
		if  (y>=x) {
				cout << "NO";
		        return 0;
			}
		x=y;
	}
	cout << "YES";
	return 0;
}

B. Keyboard Layouts

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

There are two popular keyboard layouts in Berland, they differ only in letters positions. All the other keys are the same. In Berland they use alphabet with 26 letters which coincides with English alphabet.

You are given two strings consisting of 26 distinct letters each: all keys of the first and the second layouts in the same order.

You are also given some text consisting of small and capital English letters and digits. It is known that it was typed in the first layout, but the writer intended to type it in the second layout. Print the text if the same keys were pressed in the second layout.

Since all keys but letters are the same in both layouts, the capitalization of the letters should remain the same, as well as all other characters.

Input

The first line contains a string of length 26 consisting of distinct lowercase English letters. This is the first layout.

The second line contains a string of length 26 consisting of distinct lowercase English letters. This is the second layout.

The third line contains a non-empty string s consisting of lowercase and uppercase English letters and digits. This is the text typed in the first layout. The length of s does not exceed 1000.

Output

Print the text if the same keys were pressed in the second layout.

Examples
input
qwertyuiopasdfghjklzxcvbnm
veamhjsgqocnrbfxdtwkylupzi
TwccpQZAvb2017
output
HelloVKCup2017
input
mnbvcxzlkjhgfdsapoiuytrewq
asdfghjklqwertyuiopzxcvbnm
7abaCABAABAcaba7
output
7uduGUDUUDUgudu7

B题,要求给出26个字母一一对应的变换方式,把一个字符串按变换方式转换之后输出。

直接用map搞。

#include <string.h> 
#include <map>
#include <cstdio>
#include <iostream>
#include <math.h>
#include <cmath>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
char a[1005],b[1005],c[1005];

int main() {
	map<char,char> my;
	int l='A'-'a',i;
	scanf("%s",a);
	scanf("%s",b);
	for (i=0;i<26;i++) {
		my[a[i]]=b[i];
		my[(char)(a[i]+l)]=(char)(b[i]+l);
	}
	scanf("%s",c);
	int len=strlen(c);
	for (i=0;i<len;i++) {
		if ((c[i]>='a'&&c[i]<='z')||(c[i]>='A'&&c[i]<='Z')) {
			char r=my[c[i]];
		cout << r;
		} else cout << c[i];
	}
	return 0;
}

C. Jury Marks
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Polycarp watched TV-show where k jury members one by one rated a participant by adding him a certain number of points (may be negative, i. e. points were subtracted). Initially the participant had some score, and each the marks were one by one added to his score. It is known that the i-th jury member gave aipoints.

Polycarp does not remember how many points the participant had before this k marks were given, but he remembers that among the scores announced after each of the k judges rated the participant there were n(n ≤ k) values b1, b2, ..., bn (it is guaranteed that all values bj are distinct). It is possible that Polycarp remembers not all of the scores announced, i. e. n < k. Note that the initial score wasn't announced.

Your task is to determine the number of options for the score the participant could have before the judges rated the participant.

Input

The first line contains two integers k and n (1 ≤ n ≤ k ≤ 2 000) — the number of jury members and the number of scores Polycarp remembers.

The second line contains k integers a1, a2, ..., ak ( - 2 000 ≤ ai ≤ 2 000) — jury's marks in chronological order.

The third line contains n distinct integers b1, b2, ..., bn ( - 4 000 000 ≤ bj ≤ 4 000 000) — the values of points Polycarp remembers. Note that these values are not necessarily given in chronological order.

Output

Print the number of options for the score the participant could have before the judges rated the participant. If Polycarp messes something up and there is no options, print "0" (without quotes).

Examples
input
4 1
-5 5 0 20
10
output
3
input
2 2
-2000 -2000
3998000 4000000
output
1
Note

The answer for the first example is 3 because initially the participant could have  - 1010 or 15 points.

In the second example there is only one correct initial score equaling to 4 002 000.


一个比赛,选手有个初始分数,初始的分数不知道,评委一个一个按顺序打分,一共k个评委,i(1<=i<=k)个评委评分后该选手总分是初始分数加上前i个评委的总分。现在告诉你这k个总分当中的n个分别是bi,让你求初始分数可能有多少个。


设初始分数为p.处理一下前缀和sum[i],则对任意的1<=i<=k,i名评委打分后总分就是p+sum[i]。要使n个总分都出现过,则对任意1<=j<=n, bj总能和p+sum[i]对应,则p=bj-sum[i]为定值。为了求出p,先令j=1,i取1,2,3...k其中一个,这样就求出了p。再令j=2,3,...n,验证对于这些j,是否存在sum[x]满足对应的等式p=bj-sum[x]。因为p和bj都知道,可以得

sum[x]=bj-p=bj-b1+sum[i]

只要验证sum[x]是否存在,而sum[x]的范围是-4,000,000~4,000,000,直接开个bool数组打标记就行。对于一个i,j取任意值时这个等式都能有对应的sum[x]成立,则p这个初始分数是成立的,ans++. 穷举所有i得到答案。

讲起来挺烦的,其实可以从另一个角度(形)理解:在坐标系上标出所有坐标为(i,sum[i])的点,全部上下平移可以使所有b[j]重新排列后与其中某些点重合。

还有一点需要注意的,如果sum[i]有重复的,则p求出来是一样的。为了去重,我将sum数组排了个序。

AC代码:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string.h>
#include <string> 
#include <map>
#include <algorithm>
#include <queue>
#include <math.h>
#include <cmath>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=2005;
int n,k;
int a[maxn],b[maxn],sum[maxn];
bool f[8000005];

int main() {
	int i,j;
	scanf("%d%d",&k,&n);
	sum[0]=0;
	mem0(f);
	for (i=1;i<=k;i++) {
		scanf("%d",&a[i]);
		sum[i]=sum[i-1]+a[i];
		f[sum[i]+4000000]=1;
	}
	for (i=1;i<=n;i++) {
		scanf("%d",&b[i]);
	}
	int ans=0;
	sort(sum+1,sum+k+1);
	for (i=1;i<=k;i++) {
		if (sum[i]==sum[i-1]&&i!=1) continue;
		int flag=1;
		for (j=1;j<=n;j++) {
			int d=b[j]-b[1]+sum[i]+4000000; 
			if (d<=8000000&&d>=0)
			  if (f[d]) continue;
				flag=0;
			    break;
		}
		if (flag) ans++;
	}
	printf("%d\n",ans);
	return 0;
}

D. Office Keys

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebody, it couldn't be taken by anybody else.

You are to determine the minimum time needed for all n people to get to the office with keys. Assume that people move a unit distance per 1 second. If two people reach a key at the same time, only one of them can take the key. A person can pass through a point with a key without taking it.

Input

The first line contains three integers nk and p (1 ≤ n ≤ 1 000n ≤ k ≤ 2 0001 ≤ p ≤ 109) — the number of people, the number of keys and the office location.

The second line contains n distinct integers a1, a2, ..., an (1 ≤ ai ≤ 109) — positions in which people are located initially. The positions are given in arbitrary order.

The third line contains k distinct integers b1, b2, ..., bk (1 ≤ bj ≤ 109) — positions of the keys. The positions are given in arbitrary order.

Note that there can't be more than one person or more than one key in the same point. A person and a key can be located in the same point.

Output

Print the minimum time (in seconds) needed for all n to reach the office with keys.

Examples
input
2 4 50
20 100
60 10 40 80
output
50
input
1 2 10
11
15 7
output
7
Note

In the first example the person located at point 20 should take the key located at point 40 and go with it to the office located at point 50. He spends 30 seconds. The person located at point 100 can take the key located at point 80 and go to the office with it. He spends 50 seconds. Thus, after 50 seconds everybody is in office with keys.



一个坐标轴上n个人k把钥匙分布在不同位置,这n个人需要先到达其中一个钥匙的位置捡起钥匙,再到办公室所在的坐标p处. 保证钥匙数量比人多,每个钥匙只能被一个人拿。问所有人从当前位置,先去捡钥匙再到办公室的距离的最大值最小是多少。


看到最大值最小就隐隐感觉到需要二分答案。

实际上这题解法就是二分+贪心。二分最大距离,之后再贪心,对于位置从左到右的每一个人,尽量取最左边第一个满足条件的钥匙,看能否使n个人都取到钥匙。

为什么一定是这样?假设ai<=aj,bi<=bj,ai配bi,aj配bj,将bi和bj交换,很容易就推出,交换位置之后代价一定变大。


实际上这是一个很裸的二分匹配问题,据说有人用二分距离+最大匹配过了。害怕超时,没敢写。写个最大流也可以,不过肯定会超时。比赛之后我闲的没事,用最大流模板套了一下,果然在第六个点就超时了。

AC代码:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string.h>
#include <string> 
#include <map>
#include <algorithm>
#include <queue>
#include <math.h>
#include <cmath>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=2005,inf=0x3f3f3f3f;
int a[maxn],b[maxn];

bool check(int n,int k,int mid,int p) {
	int i,j,cnt=0,top=1;
	for (i=1;i<=n;i++) {
		for (j=top;j<=k;j++) {
			int d;
			if ((p>=b[j]&&b[j]>=a[i])||(p<=b[j]&&b[j]<=a[i]))
		        d=abs(a[i]-p);
	    	else 
		        d=abs(b[j]-p)+abs(b[j]-a[i]);
		    if (d<=mid) {
		    	cnt++;
		    	top=j+1;
		    	break;
		    }
		}
	}
	return cnt==n;
}

ll solve(int n,int k,int p) {
	ll l=0,r=2*inf;
	ll ans=2*inf,mid;
	while (l<=r) {
		mid=(l+r)/2;
		if (check(n,k,mid,p)) {
			ans=mid;
			r=mid-1;
		} else l=mid+1;
	}
	return ans;
}

int main() {
	int i,j,l,r,n,k,p;
	ll ans;
	scanf("%d%d%d",&n,&k,&p);
	for (i=1;i<=n;i++) {
		scanf("%d",&a[i]);
	}
	for (i=1;i<=k;i++) {
		scanf("%d",&b[i]);
	}
	sort(a+1,a+n+1);
	sort(b+1,b+k+1);
	ans=solve(n,k,p);
	printf("%I64d\n",ans);
	return 0;
}

E. Cards Sorting
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Vasily has a deck of cards consisting of n cards. There is an integer on each of the cards, this integer is between 1 and 100 000, inclusive. It is possible that some cards have the same integers on them.

Vasily decided to sort the cards. To do this, he repeatedly takes the top card from the deck, and if the number on it equals the minimum number written on the cards in the deck, then he places the card away. Otherwise, he puts it under the deck and takes the next card from the top, and so on. The process ends as soon as there are no cards in the deck. You can assume that Vasily always knows the minimum number written on some card in the remaining deck, but doesn't know where this card (or these cards) is.

You are to determine the total number of times Vasily takes the top card from the deck.

Input

The first line contains single integer n (1 ≤ n ≤ 100 000) — the number of cards in the deck.

The second line contains a sequence of n integers a1, a2, ..., an (1 ≤ ai ≤ 100 000), where ai is the number written on the i-th from top card in the deck.

Output

Print the total number of times Vasily takes the top card from the deck.

Examples
input
4
6 3 1 2
output
7
input
1
1000
output
1
input
7
3 3 3 3 3 3 3
output
7
Note

In the first example Vasily at first looks at the card with number 6 on it, puts it under the deck, then on the card with number 3, puts it under the deck, and then on the card with number 1. He places away the card with 1, because the number written on it is the minimum among the remaining cards. After that the cards from top to bottom are [2, 6, 3]. Then Vasily looks at the top card with number 2 and puts it away. After that the cards from top to bottom are [6, 3]. Then Vasily looks at card 6, puts it under the deck, then at card 3 and puts it away. Then there is only one card with number 6 on it, and Vasily looks at it and puts it away. Thus, in total Vasily looks at 7 cards.



一叠卡片,每个上面都有数字。现在从顶开始一个个取放到牌堆底下,取到这叠卡片中数字最小的就把卡片直接取走,直到没有卡。问总共取了多少张卡。


每次找剩余序列当中最小的数的位置,算一下和前一个之间隔多少张牌就可以了。序列中有些牌已经被取走,可以利用树状数组来动态地维护这些关系。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=100005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f; 
ll f[maxn];
vector<int> v[maxn];
int n;

struct card{
	ll num,pos;
};
card a[maxn];

bool cmp(card a,card b) {
	return a.num<b.num || (a.num==b.num&&a.pos<b.pos);
}

int lowbit(int x) {
	return x&(-x);
}

ll findsum(int p) {
	ll sum=0;
	int i;
	for (i=p;i>0;i-=lowbit(i)) 
		sum+=f[i];
	return sum;
}

void update(int p,ll val) {
	int i;
	for (i=p;i<=n;i+=lowbit(i)) 
		f[i]+=val;
}

int main() {
	int i;
	scanf("%d",&n);
	mem0(f);
	for (i=1;i<=n;i++) {
		scanf("%I64d",&a[i].num);
		a[i].pos=i;
		update(i,1);
		v[a[i].num].push_back(i);
	}
	sort(a+1,a+n+1,cmp);
	ll ans=0;
	a[0].num=0;
	for (i=1;i<=n;i++) 
	    if (a[i].num!=a[i-1].num) sort(v[a[i].num].begin(),v[a[i].num].end());
	int last;
	last=ans=a[1].pos;
	update(a[1].pos,-1);
	for (i=2;i<=n;i++) {
		int pos=upper_bound(v[a[i].num].begin(),v[a[i].num].end(),last)-v[a[i].num].begin();
		if (pos==v[a[i].num].size()) pos=0;
		pos=v[a[i].num][pos];
		if (pos>=last) 
		    ans+=findsum(pos)-findsum(last);
		else 
			ans+=findsum(pos)+findsum(n)-findsum(last);
		last=pos;
		update(pos,-1);
	}
	printf("%I64d\n",ans);
	return 0;
}


F. Bamboo Partition
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Vladimir wants to modernize partitions in his office. To make the office more comfortable he decided to remove a partition and plant several bamboos in a row. He thinks it would be nice if there are n bamboos in a row, and the i-th from the left is ai meters high.

Vladimir has just planted n bamboos in a row, each of which has height 0 meters right now, but they grow 1 meter each day. In order to make the partition nice Vladimir can cut each bamboo once at any height (no greater that the height of the bamboo), and then the bamboo will stop growing.

Vladimir wants to check the bamboos each d days (i.e. d days after he planted, then after 2d days and so on), and cut the bamboos that reached the required height. Vladimir wants the total length of bamboo parts he will cut off to be no greater than k meters.

What is the maximum value d he can choose so that he can achieve what he wants without cutting off more than k meters of bamboo?

Input

The first line contains two integers n and k (1 ≤ n ≤ 1001 ≤ k ≤ 1011) — the number of bamboos and the maximum total length of cut parts, in meters.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — the required heights of bamboos, in meters.

Output

Print a single integer — the maximum value of d such that Vladimir can reach his goal.

Examples
input
3 4
1 3 5
output
3
input
3 40
10 30 50
output
32
Note

In the first example Vladimir can check bamboos each 3 days. Then he will cut the first and the second bamboos after 3 days, and the third bamboo after 6 days. The total length of cut parts is 2 + 0 + 1 = 3meters.



题意可以总结为一个数学式子:

求满足最大的d.


转化为:

只需要确定就可以求出d。

这样,我们可以对每个ai,求出所有可能的ai/d的值相同的d的选值区域区间左界。这样的区间最多有2倍根号ai个。

把所有区间左界排序,则在同一个区间里面对于不同的d是确定的,我们只要算一下此时d是否在选定的区间里,如果是就更新一下答案。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=7000005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L);
ll a[105],b[maxn];

int main() {
	int n,i,j,m=0;
	ll k,s,ans=1;
	scanf("%d%I64d",&n,&k);
	s=k;
	for (i=1;i<=n;i++) {
		scanf("%I64d",&a[i]);
		s+=a[i];
		for (j=1;j<=sqrt(a[i]);j++) {
			b[m++]=j;
			if (j*j!=a[i]) b[m++]=(a[i]+j-1)/j;
		}
	}
	sort(b,b+m);
	m=unique(b,b+m)-b;
	b[m]=llinf;
	for (i=0;i<m;i++) {
		ll sum=0,d;
		for (j=1;j<=n;j++) 
			sum+=(a[j]+b[i]-1)/b[i]; 
		d=s/sum;
		if (d>=b[i]&&d<b[i+1]) ans=max(ans,d);
	}
	printf("%I64d\n",ans);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值