5.16pkusc模拟赛1

A.切绳子,不可多条连接,求n条绳子切成k段的最大长度。
卡精度?转成cm二分。n<=10000(5.16)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define N 10005
using namespace std;
int n,k;
double a[N];int b[N];
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    long long l=1,r=(int)1e7+1;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%lf",&a[i]),b[i]=(int)((double)a[i]*100+0.5);
    while(l<r){
        int mid=(l+r)/2;
        int ans=0;
        for(int i=1;i<=n;i++) ans+=(int)(b[i]/mid);
        if(ans<k) r=mid;
        else l=mid+1;
    }
    printf("%.2lf\n",(double)(l-1)/100);
    return 0;
}

B.
C.n个数分组,连续的才能分成一组,且每组Max-Min<=k,的方案数。n<=100000(5.16)
rmq+二分/单调队列

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 100005
#define ll long long
int ffmin[N][20],ffmax[N][20];
int a[N],n,k,T;
ll ans;
bool judge(int from,int to){
//  printf("%d %d\n",from,to);
    int l=(int)log2(to-from+1);
    int mx=max(ffmax[from][l],ffmax[to-(1<<l)+1][l]);
    int mn=min(ffmin[from][l],ffmin[to-(1<<l)+1][l]);
    return mx-mn<k;
}
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    scanf("%d",&T);
    while(T--){
        ans=0;
        memset(ffmax,0,sizeof(0));
        memset(ffmin,0,sizeof(0));
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),ffmin[i][0]=a[i],ffmax[i][0]=a[i];
        int l=(int)log2(n);
        for(int i=1;i<=l;i++)
            for(int j=1;j<=n-(1<<i)+1;j++){
                ffmin[j][i]=min(ffmin[j][i-1],ffmin[j+(1<<(i-1))][i-1]);
                ffmax[j][i]=max(ffmax[j][i-1],ffmax[j+(1<<(i-1))][i-1]);
            }
        for(int i=1;i<=n;i++){
            int l=i,r=n+1;
            while(l<r){
                int mid=(l+r)/2;
                if(judge(i,mid)) l=mid+1;
                else r=mid;
            }
            ans=(ll)(ans+(l-1-i+1));
        }
        printf("%lld\n",ans);
    }
    return 0;
}

D.
E.求最小的m,使得[0,m]的线段树存在[l,r]区间节点。
0<=l

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
bool judge(ll l,ll r){
    if(l==0) return 1;
    if(l<0) return 0;
    return judge(l-(r-l+1),r)||judge(l-(r-l+1)-1,r);
}
ll solve(ll l,ll r){
    if(r==909){
        r++;r--;
    }
    if(r>2*l) {
    //  printf("**%I64d\n",r);
        return -1;
    }
    if(judge(l,r)) return r;
    ll len=(r-l+1);
    ll ans=solve(l-len-1,r);
    ll tmp=solve(l-len,r);
    if(ans==-1) ans=tmp;
    else if(tmp!=-1) ans=min(ans,tmp);
    tmp=solve(l,r+len);
    if(ans==-1) ans=tmp;
    else if(tmp!=-1) ans=min(ans,tmp);
    tmp=solve(l,r+len-1);
    if(ans==-1) ans=tmp;
    else if(tmp!=-1) ans=min(ans,tmp);
    return ans;
}
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    ll l,r;
    while(~scanf("%I64d%I64d",&l,&r)){
        if(l==0) printf("%I64d\n",r);
        else printf("%I64d\n",solve(l,r));
    }
    return 0;
}

F.

发布了87 篇原创文章 · 获赞 7 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/yxr0105/article/details/51441276
今日推荐