A. Reverse a Substring
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given a string ss consisting of nn lowercase Latin letters.
Let's define a substring as a contiguous subsegment of a string. For example, "acab" is a substring of "abacaba" (it starts in position 33and ends in position 66), but "aa" or "d" aren't substrings of this string. So the substring of the string ss from position ll to position rr is s[l;r]=slsl+1…srs[l;r]=slsl+1…sr.
You have to choose exactly one of the substrings of the given string and reverse it (i. e. make s[l;r]=srsr−1…sls[l;r]=srsr−1…sl) to obtain a string that is less lexicographically. Note that it is not necessary to obtain the minimum possible string.
If it is impossible to reverse some substring of the given string to obtain a string that is less, print "NO". Otherwise print "YES" and anysuitable substring.
String xx is lexicographically less than string yy, if either xx is a prefix of yy (and x≠yx≠y), or there exists such ii (1≤i≤min(|x|,|y|)1≤i≤min(|x|,|y|)), that xi<yixi<yi, and for any jj (1≤j<i1≤j<i) xj=yjxj=yj. Here |a||a| denotes the length of the string aa. The lexicographic comparison of strings is implemented by operator < in modern programming languages.
Input
The first line of the input contains one integer nn (2≤n≤3⋅1052≤n≤3⋅105) — the length of ss.
The second line of the input contains the string ss of length nn consisting only of lowercase Latin letters.
Output
If it is impossible to reverse some substring of the given string to obtain a string which is lexicographically less, print "NO". Otherwise print "YES" and two indices ll and rr (1≤l<r≤n1≤l<r≤n) denoting the substring you have to reverse. If there are multiple answers, you can print any.
Examples
input
Copy
7
abacaba
output
Copy
YES
2 5
input
Copy
6
aabcfg
output
Copy
NO
Note
In the first testcase the resulting string is "aacabba".
题意:
给你一个字符串,让你找出改变的位置其实和末尾,改变后可以使其的字典序变得比原串更小,只要找到就好。
题解:
既然只需要找到,那么我们只要找到第一个当前字符壁厚一个字符大的就行了,然后记录当前位置加一和加二,反正只需要满足的就可以了。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std ;
int main()
{
int n ;
scanf("%d" , &n) ;
scanf("%d" , &n) ;
string s ;
cin >> s ;
int x = 0 , y = 0 ;
for(int i = 0 ; i < n - 1 ; i ++){
if(s[i] > s[i + 1]){
x = i + 1 ;
y = i + 2 ;
break ;
}
}
if(!x || !y) printf("NO\n") ;
else printf("YES\n%d %d\n" , x , y) ;
return 0 ;
}
B. Game with Telephone Numbers
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
A telephone number is a sequence of exactly 1111 digits such that its first digit is 8.
Vasya and Petya are playing a game. Initially they have a string ss of length nn (nn is odd) consisting of digits. Vasya makes the first move, then players alternate turns. In one move the player must choose a character and erase it from the current string. For example, if the current string 1121, after the player's move it may be 112, 111 or 121. The game ends when the length of string ss becomes 11. If the resulting string is a telephone number, Vasya wins, otherwise Petya wins.
You have to determine if Vasya has a winning strategy (that is, if Vasya can win the game no matter which characters Petya chooses during his moves).
Input
The first line contains one integer nn (13≤n<10513≤n<105, nn is odd) — the length of string ss.
The second line contains the string ss (|s|=n|s|=n) consisting only of decimal digits.
Output
If Vasya has a strategy that guarantees him victory, print YES.
Otherwise print NO.
Examples
input
Copy
13
8380011223344
output
Copy
YES
input
Copy
15
807345619350641
output
Copy
NO
Note
In the first example Vasya needs to erase the second character. Then Petya cannot erase a character from the remaining string 880011223344 so that it does not become a telephone number.
In the second example after Vasya's turn Petya can erase one character character 8. The resulting string can't be a telephone number, because there is no digit 8 at all.
题意:
给你一个数字串,两个人分别进行删除操作,一人一次删除一个字符串,轮流进行删除,定义一个完美号码,就是在删除到只剩十一位时就停止,第一位是8就是完美数字串,那么Vasya就赢了,否则就输了,问你是否可以赢。
题解:
两个人轮流拿,既然这样我坑想赢肯定不拿8,二对方肯定会拿8,而且我要保证第一个是8,那么如果在11位前面的所有数字中,8的数量大于一半,那么我就肯定赢了,因为,不管你拿不拿8,我都可以剩下8,拿走不是8的,将8排在第一个,那么我就赢了,但如果不足,那么我救输了,因为不管我怎么拿,对方都可以把8拿完。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std ;
int main()
{
int n ;
scanf("%d" , &n) ;
string s ;
cin >> s ;
int num = 0 ;
for(int i = 0 ; i <= n - 11 ; i ++)
{
if(s[i] == '8') num ++ ;
}
if(num > (n - 11) >> 1) printf("YES\n") ;
else printf("NO\n") ;
return 0 ;
}
C. Alarm Clocks Everywhere
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Ivan is going to sleep now and wants to set his alarm clock. There will be many necessary events tomorrow, the ii-th of them will start during the xixi-th minute. Ivan doesn't want to skip any of the events, so he has to set his alarm clock in such a way that it rings during minutes x1,x2,…,xnx1,x2,…,xn, so he will be awake during each of these minutes (note that it does not matter if his alarm clock will ring during any other minute).
Ivan can choose two properties for the alarm clock — the first minute it will ring (let's denote it as yy) and the interval between two consecutive signals (let's denote it by pp). After the clock is set, it will ring during minutes y,y+p,y+2p,y+3py,y+p,y+2p,y+3p and so on.
Ivan can choose any minute as the first one, but he cannot choose any arbitrary value of pp. He has to pick it among the given values p1,p2,…,pmp1,p2,…,pm (his phone does not support any other options for this setting).
So Ivan has to choose the first minute yy when the alarm clock should start ringing and the interval between two consecutive signals pjpj in such a way that it will ring during all given minutes x1,x2,…,xnx1,x2,…,xn (and it does not matter if his alarm clock will ring in any other minutes).
Your task is to tell the first minute yy and the index jj such that if Ivan sets his alarm clock with properties yy and pjpj it will ring during all given minutes x1,x2,…,xnx1,x2,…,xn or say that it is impossible to choose such values of the given properties. If there are multiple answers, you can print any.
Input
The first line of the input contains two integers nn and mm (2≤n≤3⋅105,1≤m≤3⋅1052≤n≤3⋅105,1≤m≤3⋅105) — the number of events and the number of possible settings for the interval between signals.
The second line of the input contains nn integers x1,x2,…,xnx1,x2,…,xn (1≤xi≤10181≤xi≤1018), where xixi is the minute when ii-th event starts. It is guaranteed that all xixi are given in increasing order (i. e. the condition x1<x2<⋯<xnx1<x2<⋯<xn holds).
The third line of the input contains mm integers p1,p2,…,pmp1,p2,…,pm (1≤pj≤10181≤pj≤1018), where pjpj is the jj-th option for the interval between two consecutive signals.
Output
If it's impossible to choose such values yy and jj so all constraints are satisfied, print "NO" in the first line.
Otherwise print "YES" in the first line. Then print two integers yy (1≤y≤10181≤y≤1018) and jj (1≤j≤m1≤j≤m) in the second line, where yy is the first minute Ivan's alarm clock should start ringing and jj is the index of the option for the interval between two consecutive signals (options are numbered from 11 to mm in the order they are given input). These values should be chosen in such a way that the alarm clock will ring during all given minutes x1,x2,…,xnx1,x2,…,xn. If there are multiple answers, you can print any.
Examples
input
Copy
3 5
3 12 18
2 6 5 3 3
output
Copy
YES
3 4
input
Copy
4 2
1 5 17 19
4 5
output
Copy
NO
input
Copy
4 2
1 5 17 19
2 1
output
Copy
YES
1 1
题意:
就是给你一个n和m,然后接着n个数和m个数,问你是否可以找到一个数,将其然后再m个数中找到一个数,可以这样表示:
设找到的数是y,m中找到的是d,然后n个数中的每一个数都可以这样表示
a[i]=y+x*d(x=1,2,3,4.......)
如果可以就输出y和d在m中的位置,不行就输出NO。
题解:
既然要找这个y和d,那么可以知道既然每个数都可以变成y+x*d这样的形式,那么可以知道,n中的每个数之间都相差一定倍数的d,那么就知道d是左右的最大公约数,那么就求一遍所有数的最大公约数,最后找一下在m中是否能整出这个数的,就是答案了,如果没有,那么就是NO。
注意:一定要注意是1e18,要用long long型的,我就因此wa了两发,惨痛教训。。。。。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std ;
ll gcd(ll a , ll b) {return a ? gcd(b % a , a) : b ;}
ll a[300005] ;
int main()
{
ll n , m ;
scanf("%I64d %I64d" , &n , &m) ;
for(int i = 0 ; i < n ; i ++) scanf("%I64d" , &a[i]) ;
ll tmp = 0 ;
for(int i = 1 ; i < n ; i ++)
{
if(i == 1) tmp = a[i] - a[i - 1] ;
else tmp = gcd(tmp , a[i] - a[i - 1]) ;
}
ll flag = 0 ;
for(int i = 0 ; i < m ; i ++)
{
ll x ;
scanf("%I64d" , &x) ;
if(!flag)
{
if(tmp % x == 0) flag = i + 1;
}
}
if(!flag) printf("NO\n") ;
else printf("YES\n%I64d %I64d\n" , a[0] , flag) ;
return 0 ;
}
补题:
D. Beautiful Array
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array aa consisting of nn integers. Beauty of array is the maximum sum of some consecutive subarray of this array (this subarray may be empty). For example, the beauty of the array [10, -5, 10, -4, 1] is 15, and the beauty of the array [-3, -5, -1] is 0.
You may choose at most one consecutive subarray of aa and multiply all values contained in this subarray by xx. You want to maximize the beauty of array after applying at most one such operation.
Input
The first line contains two integers nn and xx (1≤n≤3⋅105,−100≤x≤1001≤n≤3⋅105,−100≤x≤100) — the length of array aa and the integer xx respectively.
The second line contains nn integers a1,a2,…,ana1,a2,…,an (−109≤ai≤109−109≤ai≤109) — the array aa.
Output
Print one integer — the maximum possible beauty of array aa after multiplying all values belonging to some consecutive subarray xx.
Examples
input
Copy
5 -2 -3 8 -2 1 -6
output
Copy
22
input
Copy
12 -3 1 3 3 7 1 3 3 7 1 3 3 7
output
Copy
42
input
Copy
5 10 -1 -2 -3 -4 -5
output
Copy
0
Note
In the first test case we need to multiply the subarray [-2, 1, -6], and the array becomes [-3, 8, 4, -2, 12] with beauty 22([-3, 8, 4, -2, 12]).
In the second test case we don't need to multiply any subarray at all.
In the third test case no matter which subarray we multiply, the beauty of array will be equal to 0.
题意:
给你n和x,然后一行是n个数,然后你可以进行一个操作,那就是将其中一个区间(区间是你定的,长度从1到n)的数都乘以x,然后要你找出最大子序列和。
题解:
这题看着很像dp,确实也是dp,但是那时候就是没有找出状态转移方程。。。。。
这题晋国分析后,可以看出来,有三种情况,二维dp。
1、当前的数一直不用进行乘x
2、当前的数开始乘x,以及连着乘x
3、当前的数不能乘x,因为我们只能改变一段区间,说一前面已经乘过x,那么这里就不能乘以x了。
所以就可以推出状态转移方程:
dp[i][0] = max(dp[i - 1][0] + a[i] , 0),当前的数不用乘x,并且不会变为负数。
dp[i][1] = max(dp[i - 1][1] + a[i] * x , max(dp[i - 1][0] + a[i] * x , 0)),当前的数是开始乘x和连着乘以x并且不会变成负数。
dp[i][2] = max(dp[i - 1] + a[i] , max(dp[i - 1][2] + a[i] , 0)),当前的数不必乘x,但前一个数要乘x以及前一个数不能乘以x。
因此得出最后结果。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std ;
ll dp[300005][3] , a[300005] ;
int main()
{
ll n , x ;
scanf("%I64d%I64d" , &n , &x) ;
for(int i = 0 ; i < n ; i ++) scanf("%I64d" , &a[i]) ;
dp[0][0] = max(a[0] , 0ll) ;
dp[0][1] = max(a[0] * x , 0ll) ;
dp[0][2] = max(a[0] , max(dp[0][1] , 0ll)) ;
ll ans = max(dp[0][0] , max(dp[0][1] , dp[0][2])) ;
for(int i = 1 ; i <= n ; i ++)
{
dp[i][0] = max(dp[i - 1][0] + a[i] , 0ll) ;
dp[i][1] = max(dp[i - 1][1] + a[i] * x , max(dp[i - 1][0] + a[i] * x , 0ll)) ;
dp[i][2] = max(dp[i - 1][1] + a[i] , max(dp[i - 1][2] + a[i] , 0ll)) ;
ans = max(dp[i][0] , max(dp[i][1] , max(ans , dp[i][2]))) ;
}
printf("%I64d\n" , ans) ;
return 0 ;
}
菜得不一样,菜出新高度。