C. Polycarp Restores Permutation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
An array of integers p1,p2,…,pnp1,p2,…,pn is called a permutation if it contains each number from 11 to nn exactly once. For example, the following arrays are permutations: [3,1,2][3,1,2], [1][1], [1,2,3,4,5][1,2,3,4,5] and [4,3,1,2][4,3,1,2]. The following arrays are not permutations: [2][2], [1,1][1,1], [2,3,4][2,3,4].
Polycarp invented a really cool permutation p1,p2,…,pnp1,p2,…,pn of length nn. It is very disappointing, but he forgot this permutation. He only remembers the array q1,q2,…,qn−1q1,q2,…,qn−1 of length n−1n−1, where qi=pi+1−piqi=pi+1−pi.
Given nn and q=q1,q2,…,qn−1q=q1,q2,…,qn−1, help Polycarp restore the invented permutation.
Input
The first line contains the integer nn (2≤n≤2⋅1052≤n≤2⋅105) — the length of the permutation to restore. The second line contains n−1n−1 integers q1,q2,…,qn−1q1,q2,…,qn−1 (−n<qi<n−n<qi<n).
Output
Print the integer -1 if there is no such permutation of length nn which corresponds to the given array qq. Otherwise, if it exists, print p1,p2,…,pnp1,p2,…,pn. Print any such permutation if there are many of them.
Examples
input
Copy
3 -2 1
output
Copy
3 1 2
input
Copy
5 1 1 1 1
output
Copy
1 2 3 4 5
input
Copy
4 -1 2 2
output
Copy
-1
题意:给出一个序列两两之间的差值,问你可以构造一个符合这个差值的序列吗。
思路:这道题的写法应该有几种,官方的题解是列出式子,然后算出第一个值就可以推出后面的值,我的想法是求一个前缀和,然后用1减去一个前缀和的最小值,然后依次加前缀和用set判重因为序列不可能出现重复的数,看值是否在1到n之间如果不在,则无法构成输出-1,否则输出答案。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<set>
#include<algorithm>
#define LL long long
#define INF 1e18
using namespace std;
const int maxn=2e5+100;
int a[maxn];
LL sum[maxn];
vector<LL>Q;
set<LL>ss;
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d",&a[i]);
}
LL Min=INF;
for(int i=1;i<n;i++)
{
sum[i]=sum[i-1]+a[i];
if(sum[i]==0||sum[i]==sum[i-1])
{
printf("-1\n");
return 0;
}
Min=min(Min,sum[i]);
}
Min=min(Min,sum[0]);
LL st=1-Min;
ss.insert(0);
for(int i=0;i<n;i++)
{
if(st+sum[i]>n||st+sum[i]<0)
{
printf("-1\n");
return 0;
}
ss.insert(sum[i]);
Q.push_back(st+sum[i]);
}
if(ss.size()<n)
{
printf("-1\n");
return 0;
}
for(int i=0;i<n;i++)
{
printf("%lld ",Q[i]);
}
printf("\n");
return 0;
}
D. Colored Boots
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
There are nn left boots and nn right boots. Each boot has a color which is denoted as a lowercase Latin letter or a question mark ('?'). Thus, you are given two strings ll and rr, both of length nn. The character lili stands for the color of the ii-th left boot and the character riri stands for the color of the ii-th right boot.
A lowercase Latin letter denotes a specific color, but the question mark ('?') denotes an indefinite color. Two specific colors are compatible if they are exactly the same. An indefinite color is compatible with any (specific or indefinite) color.
For example, the following pairs of colors are compatible: ('f', 'f'), ('?', 'z'), ('a', '?') and ('?', '?'). The following pairs of colors are notcompatible: ('f', 'g') and ('a', 'z').
Compute the maximum number of pairs of boots such that there is one left and one right boot in a pair and their colors are compatible.
Print the maximum number of such pairs and the pairs themselves. A boot can be part of at most one pair.
Input
The first line contains nn (1≤n≤1500001≤n≤150000), denoting the number of boots for each leg (i.e. the number of left boots and the number of right boots).
The second line contains the string ll of length nn. It contains only lowercase Latin letters or question marks. The ii-th character stands for the color of the ii-th left boot.
The third line contains the string rr of length nn. It contains only lowercase Latin letters or question marks. The ii-th character stands for the color of the ii-th right boot.
Output
Print kk — the maximum number of compatible left-right pairs of boots, i.e. pairs consisting of one left and one right boot which have compatible colors.
The following kk lines should contain pairs aj,bjaj,bj (1≤aj,bj≤n1≤aj,bj≤n). The jj-th of these lines should contain the index ajaj of the left boot in the jj-th pair and index bjbj of the right boot in the jj-th pair. All the numbers ajaj should be distinct (unique), all the numbers bjbj should be distinct (unique).
If there are many optimal answers, print any of them.
题意:求出有多少对上下字母相同,‘?’可以和任意字母匹配。
思路:先让26个字母相同的匹配完,然后用‘?’匹配其他字母,然后在‘?’相同匹配。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#define LL long long
using namespace std;
const int maxn=2e5+100;
struct node
{
int x,y;
};
char s1[maxn];
char s2[maxn];
vector<int>num1[30],num2[30];
vector<node>st;
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s1+1);
scanf("%s",s2+1);
for(int i=1;i<=n;i++)
{
if(s1[i]=='?')
{
num1[26].push_back(i);
}
else
{
num1[s1[i]-'a'].push_back(i);
}
if(s2[i]=='?')
{
num2[26].push_back(i);
}
else
{
num2[s2[i]-'a'].push_back(i);
}
}
int ans=0;
int pos1=0,pos2=0;
for(int i=0;i<=25;i++)
{
int v=min(num1[i].size(),num2[i].size());
for(int j=0;j<v;j++)
{
node p;
p.x=num1[i][j];
p.y=num2[i][j];
st.push_back(p);
}
int k=v;
if(num1[i].size()>v)
{
while(pos2<num2[26].size()&&k<num1[i].size())
{
node p;
p.x=num1[i][k++];
p.y=num2[26][pos2++];
st.push_back(p);
}
}
if(num2[i].size()>v)
{
while(pos1<num1[26].size()&&k<num2[i].size())
{
node p;
p.y=num2[i][k++];
p.x=num1[26][pos1++];
st.push_back(p);
}
}
}
while(pos1<num1[26].size()&&pos2<num2[26].size())
{
node p;
p.x=num1[26][pos1++];
p.y=num2[26][pos2++];
st.push_back(p);
}
ans=st.size();
printf("%d\n",ans);
for(int i=0;i<st.size();i++)
{
printf("%d %d\n",st[i].x,st[i].y);
}
return 0;
}
E. Superhero Battle
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
A superhero fights with a monster. The battle consists of rounds, each of which lasts exactly nn minutes. After a round ends, the next round starts immediately. This is repeated over and over again.
Each round has the same scenario. It is described by a sequence of nn numbers: d1,d2,…,dnd1,d2,…,dn (−106≤di≤106−106≤di≤106). The ii-th element means that monster's hp (hit points) changes by the value didi during the ii-th minute of each round. Formally, if before the ii-th minute of a round the monster's hp is hh, then after the ii-th minute it changes to h:=h+dih:=h+di.
The monster's initial hp is HH. It means that before the battle the monster has HH hit points. Print the first minute after which the monster dies. The monster dies if its hp is less than or equal to 00. Print -1 if the battle continues infinitely.
Input
The first line contains two integers HH and nn (1≤H≤10121≤H≤1012, 1≤n≤2⋅1051≤n≤2⋅105). The second line contains the sequence of integers d1,d2,…,dnd1,d2,…,dn (−106≤di≤106−106≤di≤106), where didi is the value to change monster's hp in the ii-th minute of a round.
Output
Print -1 if the superhero can't kill the monster and the battle will last infinitely. Otherwise, print the positive integer kk such that kk is the first minute after which the monster is dead.
Examples
input
Copy
1000 6 -100 -200 -300 125 77 -4
output
Copy
9
input
Copy
1000000000000 5 -1 0 0 0 0
output
Copy
4999999999996
input
Copy
10 4 -3 -6 5 4
output
Copy
-1
题意:给出n个数,然后给出一个值让这个值去依次去加这n个数,可以循环加,问操作多少次可以让这个值小于等于0,如果永远不能变成0则输出-1.
思路:先求前缀和如果大于0,则看第一次能否实现,如果不能则输出-1,否则就二分答案(判断的时候只要看最后一轮能否用最小值使答案成立),具体看代码。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
#define INF 1e18
using namespace std;
const int maxn=2e5+100;
LL a[maxn],sum[maxn];
LL Min=INF,h;
int n;
bool check(LL x)
{
if(h+(x-1)*sum[n]<=abs(Min))
{
return true;
}
else
{
return false;
}
}
int main()
{
scanf("%lld%d",&h,&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
Min=min(sum[i],Min);
}
LL v=h,flag=1,pos=1;
if(sum[n]>=0)
{
for(int i=1;i<=n;i++)
{
v+=a[i];
if(v<=0)
{
pos=i;
break;
}
}
if(v>0)
{
flag=0;
}
if(!flag)
{
printf("-1\n");
return 0;
}
else
{
printf("%d\n",pos);
return 0;
}
}
LL l=0,r=h/(sum[n]*(-1))+2;
//cout<<l<<" "<<r<<endl;
while((r-l)>1)
{
LL mid=(l+r)/2;
//cout<<l<<" "<<r<<endl;
if(check(mid))
{
r=mid;
}
else
{
l=mid;
}
}
LL ans=(r-1)*n;
v=h+(r-1)*sum[n];
for(int i=1;i<=n;i++)
{
v+=a[i];
ans++;
if(v<=0)
{
break;
}
}
printf("%lld\n",ans);
return 0;
}