A . Three swimmers
题解
找p离a,b,c倍数最近的那个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include<bits/stdc++.h> using namespace std; long long mod=1000000007; long long ans,a,b,c,p; int main(){ int t; scanf("%d",&t); while(t--){ scanf("%lld%lld%lld%lld",&p,&a,&b,&c); ans=a-((p-1)%a+1); ans=min(ans,b-((p-1)%b+1)); ans=min(ans,c-((p-1)%c+1)); printf("%lld\n",ans); } return 0; }
|
B . Card Deck
题解:
使值大的尽量在底下,每次取都取到当前剩的最大的一个
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
| #include<bits/stdc++.h> using namespace std; long long mod=1000000007; int const maxn=1e5+7; typedef long long ll; ll n,a[maxn],ne[maxn],ans; int p[maxn]; int main(){ int t; scanf("%d",&t); while(t--){
scanf("%lld",&n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); p[1]=1; for(int i=2;i<=n;i++){ if(a[i]>a[p[i-1]])p[i]=i; else p[i]=p[i-1]; } int qwq=n,tot=0; while(qwq>0){ for(int i=p[qwq];i<=qwq;i++){ ne[++tot]=a[i]; } qwq=p[qwq]-1; } for(int i=1;i<n;i++){ printf("%lld ",ne[i]); } printf("%lld\n",ne[n]); } return 0; }
|
C . Maximum width
题意:
给出长度为n的字符串s,长度为m的字符串t
求构造一个长度m递增数列p, \[1 \leq p_{1} \le p_{2} \le \ldots \le p_{m} \leq n\] 满足 \(s_{pi} = t_i\) , p的宽度定义为 \(\max _{1 \leq i<m}\left(p_{i+1}-p_{i}\right)\),即最大的相 邻的差
保证一定能构造出一组p,求p的最大宽度
数据范围:
\[\left( 2 \leq m \leq n \leq 2 \cdot 10^{5}\right)\]
题解:
使相邻的pi 和 pi+1 差最大,就要使pi取尽量靠左的s中的位置,pi+1取尽量靠右的s中的位置
为了维护p递增,先从左向右扫一遍维护出最小值pl,再从右向左扫一遍维护出最大值pr,再扫一遍枚举分界点 \[ans=max \left( pr[i+1]-pl[i] \right)\]
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
| #include<bits/stdc++.h> using namespace std; int const maxn2=2e5+7; int l[maxn2],r[maxn2],n,m; string s1,s2; int main(){ scanf("%d%d",&n,&m); cin>>s1>>s2; int ans=-maxn2; int qwq=0; for(int j=0;j<m;j++){ while(s1[qwq]!=s2[j])qwq++; l[j]=qwq; qwq++; } qwq=n-1; for(int j=m-1;j>=0;j--){ while(s1[qwq]!=s2[j])qwq--; r[j]=qwq; qwq--; } for(int i=0;i<m-1;i++){ ans=max(r[i+1]-l[i],ans); } printf("%d\n",ans);
return 0; }
|
比赛时:
我居然忘记了p是递增的,直接求了pi+1在s中的最右减去,pi在s中的最左。。。。
假题意代师。。。
D . Genius's Gambit
题意:
构造两个含a个0,b个1的二进制数x,y(x>=y),两者之差的二进制数含k个1。
数据范围:\[(0≤a, 1≤b; 0≤k≤a+b≤2⋅10^5)\]
题解:
两个错位的1和0,中间全部相同,能减出一组1,例如:
\[11110000-\\01110001=\\01111111\]
利用这个规律可以构造出所有a+b-2>=k (k,a>=1,b>=2)的情况
特判:只有0个0的,或者1个1(因为不允许前导零),不能构造出1。k=0时一定能满足。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| a,b,k=map(int,input().split()) if(k==0): s='1'*b+'0'*a print("Yes\n"+s+"\n"+s) elif(a==0): print("No"); else: if a+b-2<k or b==1: print("No") else: s='1'*(b-1)+'0'*(a-1) print("Yes") print(s[:a+b-k-1]+'1'+s[a+b-k-1:]+'0') print(s[:a+b-k-1]+'0'+s[a+b-k-1:]+'1')
|
比赛时:
没有想到只要错位中间一样就可以了。。以为要分0和1讨论
没有想到k=0一定满足
没有注意到1个1,或者0个0都不能构造出来。
比完赛简直是面向样例编程。。。
E . Almost Fault-Tolerant Database
题意:
n个m长的数组,
构造一个数组,满足它改变最多两个值可以得到任意一个给出的n个数组
不存在输出no
数据范围:
\[(2 \leq n ; 1 \leq m ; n \cdot m \leq 250000)\]
题解:
网上看到的。枚举构造
假设以第一个数组为模板,跟后面的作对比
有数组跟它>4个不同,则无解
所有的<=两个不同,则直接输出第一个数组
有4个不同,则第一个数组至少要改2位,枚举改的两位和改的值
有3个不同,如果有一位所有3个的都有且为同一个值,则改这一位,否则等同于第三种情况,枚举改哪两位哪个值,