A. Rating Increase
题意:将一个字符串分成两个整数,一个a,一个b, b必须大于a并且不能有前导0。
思路:因为没有前导0,所以从第一个数字开始取,取到第一个不是零的数字结束,剩下的字符就是下一个整数,比较大小判断-1即可。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 2e5 + 7 ;
inline int read(){
int x = 0 , f = 1 ;
char c = getchar() ;
while(c > '9' || c < '0'){
if(c == '-')
f = -1 ;
c = getchar() ;
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
char s[maxn] ;
int t , n , q , a[maxn] ;
ll sum[maxn] ;
void solve(){
scanf("%s" , s + 1) ;
n = strlen(s + 1) ;
int ans = 0 ;
ans = (s[1] - '0') ;
int rt = -1 ;
for(int i = 2 ; i <= n ; i ++){
if(s[i] != '0'){
rt = i ;
break ;
}
else{
ans = ans * 10 + (s[i] - '0') ;
}
}
int SS = 0 ;
for(int i = rt ; i <= n ; i ++){
SS = SS * 10 + (s[i] - '0') ;
}
if(ans >= SS){
cout << -1 << endl ;
return ;
}
else{
cout << ans << " " << SS << endl ;
}
}
int main(){
t = read() ;
while(t --){
solve() ;
}
return 0 ;
}
B. Swap and Delete
题意:给你一个字符串只包含0和1,你有两个操作,第一个是删除一个字符,消耗1金币。第二个是交换两个字符, 不消耗金币。求和原字符串每一位都不相同的最小代价是多少?
思路:这个题我想了很久,读不太懂题意,看了官方给的提示后,豁然开朗。首先是比较修改后的字符串和原串的差异,像最后一个样例111100,最佳修改完之后是swap(a[1],a[5]) , swap(a[2],a[6]) ,是001111,可以看到要删去后面四个一,所以答案是4。所以这个题就很明朗了,首先统计0和1的个数,然后从1开始遍历,修改前x个0和前y个1,最后扫一遍看看出现一样的第一个位置在哪,输出n - i + 1即可。如果没有输出则输出0;渐进复杂度O(n)。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 2e5 + 7 ;
inline int read(){
int x = 0 , f = 1 ;
char c = getchar() ;
while(c > '9' || c < '0'){
if(c == '-')
f = -1 ;
c = getchar() ;
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
char s[maxn] , S[maxn] ;
int t , n , q , a[maxn] ;
ll sum[maxn] ;
void solve(){
scanf("%s" , s + 1) ;
n = strlen(s + 1) ;
if(n == 1){
cout << 1 << endl ;
return ;
}
int cnt = 0 ;
int rt = -1 ;
int ling = 0 , yi = 0 ;
for(int i = 1 ; i <= n ; i ++){
if(s[i] == '0'){
ling ++ ;
}
else{
yi ++ ;
}
}
for(int i = 1 ; i <= n ; i ++){
S[i] = s[i] ;
}
for(int i = 1 ; i <= n ; i ++){
if(S[i] == '0'){
if(yi > 0){
S[i] = '1' ;
yi -- ;
}
continue ;
}
if(S[i] == '1'){
if(ling > 0){
S[i] = '0' ;
ling -- ;
}
}
}
for(int i = 1 ; i <= n ; i ++){
if(s[i] == S[i]){
cout << n - i + 1 << endl ;
return ;
}
}
cout << 0 << endl ;
}
int main(){
t = read() ;
while(t --){
solve() ;
}
return 0 ;
}
C. Game with Multiset
题意:有m个操作,有add(x) , 和get(x)两个操作,add(x)是添加一个2的x次方进入集合,get(x)是看看集合中能否有元素相加可以组成x,特此空集为0.
思路:首先看m的范围1e5 ,很显然可以用O(n)或者O(nlongn)来解决问题。又看到幂次最大就是30,可以想到用O(30 * m)的复杂度来解决。这题很明显是个贪心,从大到小贪,和x比较大小,不用二分或者其他的那么麻烦,直接枚举看看最后减完是否为0即可。当然了还需要一些STL的帮助。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 2e5 + 7 ;
inline ll read(){
ll x = 0 , f = 1 ;
char c = getchar() ;
while(c > '9' || c < '0'){
if(c == '-')
f = -1 ;
c = getchar() ;
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0' ;
c = getchar() ;
}
return x * f ;
}
char s[maxn] , S[maxn] ;
ll t , n , q , a[maxn] ;
ll sum[maxn] ;
int main(){
n = read() ;
map < ll , ll > mp ;
while(n --){
ll op , u ;
op = read() ;
u = read() ;
if(op == 1){
mp[u] ++ ;
}
if(op == 2){
if(u == 0){
cout << "YES\n" ;
continue ;
}
for(int i = 30 ; i >= 0 ; i --){
if(u >= (1 << i)){
ll res = u / (1 << i) ;
u -= min(res , mp[i]) * (1 << i) ;
}
}
if(u == 0){
cout << "YES\n" ;
continue ;
}
printf("NO\n") ;
}
}
return 0 ;
}
备注:如果题解思路不同或者有问题和意见及时指正。
喜欢作者的话记得点赞收藏加关注哦~