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.
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.
Print "YES" if the given array is unimodal. Otherwise, print "NO".
You can output each letter in any case (upper or lower).
6 1 5 5 5 4 2
YES
5 10 20 30 20 10
YES
4 1 2 1 2
NO
7 3 3 3 3 3 3 3
YES
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;
}
直接用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;
}
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.
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.
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).
4 1 -5 5 0 20 10
3
2 2 -2000 -2000 3998000 4000000
1
The answer for the first example is 3 because initially the participant could have - 10, 10 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;
}
看到最大值最小就隐隐感觉到需要二分答案。
实际上这题解法就是二分+贪心。二分最大距离,之后再贪心,对于位置从左到右的每一个人,尽量取最左边第一个满足条件的钥匙,看能否使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;
}
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.
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.
Print the total number of times Vasily takes the top card from the deck.
4 6 3 1 2
7
1 1000
1
7 3 3 3 3 3 3 3
7
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;
}
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?
The first line contains two integers n and k (1 ≤ n ≤ 100, 1 ≤ 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.
Print a single integer — the maximum value of d such that Vladimir can reach his goal.
3 4 1 3 5
3
3 40 10 30 50
32
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;
}