問題はこちら
No.507 ゲーム大会(チーム決め) - yukicoder
K君以外の人のスコアを昇順にソートしておく
何点の人と組めばよいかを二分探索で求める。
X点の組がM位タイ以内に入れるというのは、X点より真に大きな点の組がM組未満であることと同値
これは尺取法によりO(N)で求まる。
二分探索が収束するまでO(logN)回やるので全体としてはO(NlogN)
a[1<<17];n,M,l,r,m,ll,rr,k;
c(int*p,int*q){return*p-*q;}
main(){
scanf("%d%d",&n,&M);
for(int i=0;i<n;i++)scanf("%d",a+i);
qsort(a+1,n-1,4,c);
l=0;r=n;
while(r-l>1){
m=(l+r)/2;
ll=1;rr=n-1;k=0;
while(ll<rr){
if(ll==m)ll++;
else if(rr==m)rr--;
else if(a[ll]+a[rr]>a[0]+a[m])k++,ll++,rr--;
else ll++;
}
if(k<M)r=m;
else l=m;
}
printf("%d",r==n?-1:a[r]);
}
まずはこの部分を縮める
if(ll==m)ll++;
else if(rr==m)rr--;
else if(a[ll]+a[rr]>a[0]+a[m])k++,ll++,rr--;
else ll++;
rr==m?rr--:
ll==m?ll--:
a[ll]+a[rr]>a[0]+a[m]?k++,ll++,rr--:ll++;
rr==m?rr--:
(ll!=m&&a[ll]+a[rr]>a[0]+a[m]?k++,rr--:0,ll++);
rr-m?ll-m&&a[ll]+a[rr]>a[0]+a[m]?k++,rr--:0,ll++:rr--;
読み込みを全部aにまとめる。indexのズレに気をつけながら縮めると
a[1<<17],p,q,l,r,m;
c(int*p,int*q){m=*p-*q;}
main(k){
for(l=2;~scanf("%d",a+r);r++);
for(qsort(a+3,r-3,4,c);r-l>1;k<a[1]?r=m:(l=m))
for(m=l+r>>1,p=3,q=*a+1,k=0;p<q;q-m?p-m&&a[p]+a[q]>a[2]+a[m]?q--,k++:0,p++:q--);
printf("%d",a[r]?:-1);
}
ぐっと睨んで、一番短くなるようにindexをずらす
a[1<<17],p,q,l,r,m;c(int*p,int*q){m=*p-*q;}main(k){for(l=2;~scanf("%d",a+r);r++);for(qsort(a+3,r-3,4,c);r-l>1;k<a[1]?r=m:(l=m))for(m=l+r>>1,p=3,q=*a+1,k=0;p<q;q-m?p-m&&a[p]+a[q]>a[2]+a[m]?q--,k++:0,p++:q--);printf("%d",a[r]?:-1);}
a[1<<17],p,q,k,r,m;c(int*p,int*q){m=*p-*q;}main(l){for(;~scanf("%d",a-1+r);r++);for(qsort(a+2,r-3,4,c);r-l>1;k<*a?r=m:(l=m))for(m=l+r>>1,p=2,q=a[-1],k=0;p<q;q-m?p-m&&a[p]+a[q]>a[1]+a[m]?q--,k++:0,p++:q--);printf("%d",a[r]?:-1);}
a[1<<17],p,q,l,r,m;c(int*p,int*q){m=*p-*q;}main(k){for(;~scanf("%d",a-2+r);r++);for(qsort(a+1,r-3,4,c);r-l>1;k<a[-1]?r=m:(l=m))for(m=l+r>>1,p=1,q=a[-2],k=0;p<q;q-m?p-m&&a[p]+a[q]>*a+a[m]?q--,k++:0,p++:q--);printf("%d",a[r]?:-1);}
a[1<<17],p,q,k,r,m;c(int*p,int*q){m=*p-*q;}main(l){for(;~scanf("%d",a-3+r);r++);for(qsort(a,r-3,4,c);r+l>1;k<a[-2]?r=m:(l=-m))for(m=r-l>>1,q=a[-3],p=k=0;p<q;q-m?p-m&&a[p]+a[q]>a[-1]+a[m]?q--,k++:0,p++:q--);printf("%d",a[r]?:-1);}
ということで結局一番短くなるのは上から2番目の
a[1<<17],p,q,k,r,m;
c(int*p,int*q){m=*p-*q;}
main(l){
for(;~scanf("%d",a-1+r);r++);
for(qsort(a+2,r-3,4,c);r-l>1;k<*a?r=m:(l=m))
for(m=l+r>>1,p=2,q=a[-1],k=0;p<q;q-m?p-m&&a[p]+a[q]>a[1]+a[m]?q--,k++:0,p++:q--);
printf("%d",a[r]?:-1);
}
228B