0%

Codeforces Round 474 A-D 题解

Codeforces Round 474 A-D 题解

960A Check the string

字符串满足abc按顺序排列且a的数量与c相同或者b的数量与c相同时候输出yes。
首先特判字符串首部肯定为a,后面每个字符的ascii值一定要大于等于前一个字符(不然不符合abc的顺序),扫描时记录下abc的个数,判断输出即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>

using namespace std;

int main()
{
string s;
int a=1,b=0,c=0,ans=0;
cin>>s;
int len = s.length();
if(s[0]!='a')
{
cout<<"NO"<<endl;
return 0;
}
for(int i=1; i<len; i++)
{
if(s[i]<s[i-1])
{
cout<<"NO"<<endl;
return 0;
}
if(s[i]=='a')
a++;
else if(s[i]=='b')
b++;
else if(s[i]=='c')
c++;
}
if(a==0''b==0''c==0)
cout<<"NO"<<endl;
else if(a==c''b==c)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}

960B Minimize the error

要使得上下两个数列差的平方和最小,而上下两个数组的操作可以相当于合并,所以K1和K2可以相加为同一个数。
我们使用一个优先队列维护上下两个数组的差,这样保证每次减去的都是数列中差值最大的。
只有让每个数平均的减小才能实现最后平方和最小,所以每次给队列首部最大的一个数减去1。
维护有限队列时,不能让其出现负数,负数的平方是大于0的但是负数会排在0之后,所以当优先队列顶部出现0的时候将其值改为1,就能保证当前队列所有都为正数且平均的减小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000+10;
long long x[maxn],y[maxn];
priority_queue<long long> q;

int main(){
int n,k1,k2;
cin >> n >> k1 >> k2;
while(!q.empty()) q.pop();
for(int i=0;i<n;i++)
cin >> x[i];
for(int i=0;i<n;i++){
cin >> y[i];
q.push(abs(x[i]-y[i]));
}
long long k = k1 + k2,temp;
while(k > 0){
if(q.top()>0)
temp = q.top() - 1;
else
temp = 1;
q.pop();
q.push(temp);
k--;
}
long long sum = 0;
while(!q.empty()){
sum += q.top() * q.top();
q.pop();
}
cout << sum << endl;
return 0;
}

960C Subsequence Counting

一个字符串有X个子串的最大值间区最小值大差一定小于等于D。
一个串有2^n-1个子串,我们就需要保证每个连续的字串差值尽可能的小,不难想到从1开始取,每次出现连续mid个相同的数,就会有2^mid-1个子串,每次减少mid值找到满足X剩余数量的mid值,构造即可,此题是special judge,所有有很多种构造方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <bits/stdc++.h>

using namespace std;

const int N = 10000+5;
long long x,d;
long long a[N];
int main()
{
cin>>x>>d;
long long l=0,i=0;
int mid=30;
while(x)
{
int t=pow(2,mid)-1;
while(t>x)
{
mid--;
t=pow(2,mid)-1;
}
x-=t;
for(int j=0; j<mid; j++)
a[l++]=d+i*d;
i++;
}
cout << l << endl;
for(int i=0; i<l-1; i++)
cout<<a[i]<<" ";
cout<<a[l-1]<<endl;
return 0;
}

960D Full Binary Trr Queries

使用数组维护每次1操作和2操作的位移量,每次维护的时候要使用取模不能超过该行行数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <bits/stdc++.h>

using namespace std;
const int N = 62;
long long a[N],b[N];
long long mod[N];

int main()
{
//ios_base::sync_with_stdio(false);
mod[0]=1;
for(int i=1;i<N;i++){
mod[i]=mod[i-1]*2;
}
int n,type;
cin>>n;
while(n--){
scanf("%d",&type);
if(type==1){
long long x,k;
scanf("%lld%lld",&x,&k);
int layer=log2(x);
a[layer]=(a[layer]+k+mod[N-1])%mod[layer];
}
if(type==2){
long long x,k;
scanf("%lld%lld",&x,&k);
int layer=log2(x);
k=(k+mod[N-1])%mod[layer];
for(int i=layer;i<62;i++){
a[i]=(a[i]+k*mod[i-layer])%mod[i];
}
}
if(type==3){
long long x;
scanf("%lld",&x);
int layer=log2(x);
if(x==1) {
printf("%lld\n",x);
continue;
}
printf("%lld ",x);
b[layer]=x+a[layer]-mod[layer];
for(int i=layer-1;i>=1;i--){
b[i]=(b[layer]/mod[layer-i]-a[i]+mod[i])%mod[i];
}
for(int i=layer-1;i>=1;i--){
printf("%lld ",mod[i]+b[i]);
}
printf("%lld\n",1+b[0]);
}
}
return 0;
}