Codeforces Round #704 (Div. 2)
CF1492A
按照题意模拟即可。注意ceil会有精度误差。
code:
#include<cstdio>
#include<cmath>
#include<bits/stdc++.h>
using namespace std;
long long t,a,b,n,m;
inline long long ceil(long long x,long long y){return x/y+(x%y!=0);}
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld%lld",&n,&m,&a,&b);
printf("%lld\n",min(ceil(n,m)*m,min(ceil(n,a)*a,ceil(n,b)*b))-n);
}
}
CF1492B
显然把大的放前面一定更优,那就开个桶从大到小扫即可。
code:
#include<cstdio>
using namespace std;
int n,m,k,x,y,z,flag[100039],t,a[100039],head,now;
int main(){
register int i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);head=n;
for(i=1;i<=n;i++) scanf("%d",&a[i]),flag[a[i]]=i;
for(i=n;i;i--){
if(!flag[i]) continue;now=flag[i];
for(j=flag[i];j<=head;j++) printf("%d ",a[j]),flag[a[j]]=0;head=now-1;
}
printf("\n");
}
}
CF1492C
枚举断点\(x\),从左往右维护\(l\)使得\(l\)是满足最小的能表示\(1\)到\(x\)的左端点,\(r\)同理,取最大值即可。
code:
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int t,n,m,k,x,y,z,l[200039],r[200039],ans;
char a[200039],b[200039];
int main(){
register int i;
scanf("%d%d",&n,&m);scanf("%s",a+1);scanf("%s",b+1);
r[m+1]=n+1;
for(i=m;i;i--){
r[i]=r[i+1]-1;
while(a[r[i]]!=b[i])
r[i]--;
}
l[0]=0;
for(i=1;i<=m;i++){
l[i]=l[i-1]+1;
while(a[l[i]]!=b[i]) l[i]++;
}
for(i=1;i<m;i++) ans=max(ans,r[i+1]-l[i]);
printf("%d\n",ans);
}
CF1492D
手玩一下就可以发现只要一对位置相距\(k\)且A在开始点为\(1\),B在结束点为\(1\),其余都相同即可。
注意特判特殊情况。
code:
#include<bits/stdc++.h>
using namespace std;
int n ,m,k,x,y,z,a[1000039],b[1000039];
int main(){
// freopen("1.in","r",stdin);
register int i;
scanf("%d%d%d",&y,&x,&n);m=x+y;
if((x<=1&&n)||(n>=m-1&&n)){printf("No\n");return 0;}
if(!y){
if(!n){
printf("Yes\n");
for(i=1;i<=x;i++) printf("1");printf("\n");
for(i=1;i<=x;i++) printf("1");
}
else printf("No");return 0;
}
if(!n){
printf("Yes\n");
for(i=1;i<=x;i++) printf("1");
for(i=1;i<=y;i++) printf("0");printf("\n");
for(i=1;i<=x;i++) printf("1");
for(i=1;i<=y;i++) printf("0");return 0;
}
x--;
a[1]=1;a[m-n]=1;x--;
for(i=2;i<=m;i++){
if(a[i]) continue;if(!x) break;
a[i]=1,x--;
}
for(i=1;i<=m;i++)b[i]=a[i];
b[m-n]=0;b[m]=1;
printf("Yes\n");
for(i=1;i<=m;i++) printf("%d",a[i]);printf("\n");
for(i=1;i<=m;i++)printf("%d",b[i]);
}
CF1492E
这里不是正解是随机化乱搞。
首先我们可以完全随机的随机化,这个可以过system test
后来出题人过来卡掉了完全随机。
这时我们可以去重后再随机。然而你发现这个连pretest都过不去了。
所以我们去重时要加权,若原来有\(2k\)个相同的放入\(2\)个即可。
然而EI又过来卡掉了这个做法。
然后我们发现如果当前已经有不满足为\(2\)的节点那么就必须选这个节点所代表的权值了。这样就能过EI的数据了。
然而EI发现不对劲又反手一组数据卡掉了。
我们发现只有\(n=4\)的时候能卡随机化。那么我们只要正向做一遍,反向做一遍,相当于做\(n=2\)成功率就大得多。
然后就过了。
现在正在求hack
code:
#include<bits/stdc++.h>
#define R(n) rand()*rand()%(n)+1
using namespace std;
int n,m,k,x,y,z,flag[250039],fl,a[250039],c[250039],cnt,ans;
double s;
vector<int> f[250039],g[250039],fs[250039];
int main(){
// freopen("1.in","r",stdin);
srand(time(0));
register int i,j,h;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
f[i].push_back(0);
for(j=1;j<=m;j++) scanf("%d",&x),f[i].push_back(x);
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++) c[j]=f[j][i];
sort(c+1,c+n+1);
g[i].push_back(0);fs[i].push_back(0);
for(j=1;j<=n;j=h){
for(h=j;h<=n;h++) if(c[j]!=c[h]) break;
cnt=h-j;while(cnt>0) g[i].push_back(c[j]),cnt-=R(6);fs[i].push_back(c[j]);
}
}
while(1){
if(clock()>500) break;fl=ans=0;
for(i=1;i<=m;i++){
x=R(g[i].size()-1);
if(ans){
for(j=1;j<=g[i].size();j++) if(g[i][j]==f[ans][i]){x=j;break;}
}
for(j=1;j<=n;j++)
if(f[j][i]!=g[i][x]) {
flag[j]++;
if(flag[j]==2){
ans=j;
}
if(flag[j]>2){fl=1;break;}
}
a[i]=x;
if(fl) break;
}
if(fl){
for(i=1;i<=n;i++) flag[i]=0;
}
else{
printf("Yes\n");
for(i=1;i<=m;i++) printf("%d ",g[i][a[i]]);return 0;
}
}
while(1){
if(clock()>1450) break;fl=ans=0;
for(i=1;i<=m;i++){
x=R(fs[i].size()-1);
if(ans){
for(j=1;j<=fs[i].size();j++) if(fs[i][j]==f[ans][i]){x=j;break;}
}
for(j=1;j<=n;j++)
if(f[j][i]!=fs[i][x]) {
flag[j]++;
if(flag[j]==2){
ans=j;
}
if(flag[j]>2){fl=1;break;}
}
a[i]=x;
if(fl) break;
}
if(fl){
for(i=1;i<=n;i++) flag[i]=0;
}
else{
printf("Yes\n");
for(i=1;i<=m;i++) printf("%d ",fs[i][a[i]]);return 0;
}
}
while(1){
if(clock()>1950) break;fl=ans=0;
for(i=m;i;i--){
x=R(fs[i].size()-1);
if(ans){
for(j=1;j<=fs[i].size();j++) if(fs[i][j]==f[ans][i]){x=j;break;}
}
for(j=1;j<=n;j++)
if(f[j][i]!=fs[i][x]) {
flag[j]++;
if(flag[j]==2){
ans=j;
}
if(flag[j]>2){fl=1;break;}
}
a[i]=x;
if(fl) break;
}
if(fl){
for(i=1;i<=n;i++) flag[i]=0;
}
else{
printf("Yes\n");
for(i=1;i<=m;i++) printf("%d ",fs[i][a[i]]);return 0;
}
}
printf("No\n");
}