10.2 考试

100+100+10 rank 1
T1,每一个点向两边拓展至(x-w,x+w)的线段,找最多条不相交的线段就好了。
T2裸线段树
T3,发现答案是连续的一段,二分左右端点暴力计算,又发现对于每个数的答案就是它每一个是一的位那一行的杨辉三角摞起来。
数组越界100->10,hh
T1

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 200050
#define inf 0x7fffffff
using namespace std;
struct data{
    long long l,r;
    bool operator < (const data &a)const{
        return (r==a.r)?(l<a.l):(r<a.r);
    }
}d[N];
int n;
int main(){
    scanf("%d",&n);
    for(int i=1,x,w;i<=n;i++){
        scanf("%d%d",&x,&w);
        d[i].l=x-w;
        d[i].r=x+w;
    }
    sort(d+1,d+n+1);
    int R=-inf; int num=0;
    for(int i=1;i<=n;i++){
        if(d[i].l>=R){
            num++;
            R=d[i].r;
        }
    }
    printf("%d\n",num);
    return 0;
}

T2

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define N 100500
#define LL long long
using namespace std;
int n,m;
LL a[N],maxn[4*N],sum[4*N];


void pushup(int rt){
    maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int rt,int l,int r){
    if(l==r){
        maxn[rt]=sum[rt]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
LL query(int rt,int l,int r,int x,int y){
    if(x<=l&&r<=y)return sum[rt];
    int mid=(l+r)>>1;
    if(y<=mid)return query(rt<<1,l,mid,x,y);
    if(x>mid)return query(rt<<1|1,mid+1,r,x,y);
    return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y);
}
void blqm(int rt,int l,int r,int x){
    if(l==r){
        a[l]%=x;maxn[rt]%=x;sum[rt]%=x;
        return;
    }
    int mid=(l+r)>>1;
    if(maxn[rt<<1]>=x)blqm(rt<<1,l,mid,x);
    if(maxn[rt<<1|1]>=x)blqm(rt<<1|1,mid+1,r,x);
    pushup(rt);
}
void work_mod(int rt,int l,int r,int x,int y,int z){
    if(x<=l&&r<=y){
        if(maxn[rt]>=z)blqm(rt,l,r,z);
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid)work_mod(rt<<1,l,mid,x,y,z);
    if(y>mid) work_mod(rt<<1|1,mid+1,r,x,y,z);
    pushup(rt);
}
void change(int rt,int l,int r,int x,LL y){
    if(l==r){
        a[x]=maxn[rt]=sum[rt]=y;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)change(rt<<1,l,mid,x,y);
    else change(rt<<1|1,mid+1,r,x,y);
    pushup(rt);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    build(1,1,n);
    int opt,l,r,x,y;
    for(int i=1;i<=m;i++){
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d%d",&l,&r);
            printf("%lld\n",query(1,1,n,l,r));
        }
        if(opt==2){
            scanf("%d%d%d",&l,&r,&x);
            work_mod(1,1,n,l,r,x);
        }
        if(opt==3){
            scanf("%d%d",&x,&y);
            change(1,1,n,x,(LL)y);
        }
    }
    return 0;
}

T3

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define LL long long
using namespace std;
long long m,bit[65],C[65][65];
LL num[65];
int k;
LL check(LL  x){
    if(!x)return -1;
    LL xx=x;
    int a[70]={0},pos=0,num=0;
    LL ans=0;
    while(x){a[++pos]=(x%2);x=x/2;}
    for(int i=pos;i;i--){
        if(a[i]){
            num++;
            if(num>k)break//!!!!!!!!!!!!!!!!
            ans+=C[i-1][k-num];
        }
    }
    return ans;
}
int main(){
    bit[0]=1;
    for(int i=1;i<=62;i++)bit[i]=bit[i-1]*2;
    C[0][0]=1;
    for(int i=1;i<=62;i++){
        C[i][0]=1;
        for(int j=1;j<=i;j++)
            C[i][j]=C[i-1][j-1]+C[i-1][j];
    }
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%d",&m,&k);
        if(k==1){printf("1 -1\n");continue;}
        if(k==64){printf("1 9223372036854775807\n");continue;}
        if(k==63){printf("1 4611686018427387903\n");continue;}
        LL l=1,r=bit[62],mid,ans1,ans2,L,R;
        while(l<=r){
            mid=(l+r)>>1;
            ans1=check(mid-1);
            ans2=check(mid);
            if(ans1<m&&ans2==m){L=mid;break;}
            if(ans1>=m){L=r=mid-1;}
            if(ans2<m){L=l=mid+1;}
        }
        l=1,r=bit[62];
        while(l<=r){
            mid=(l+r)>>1;
            ans1=check(mid);
            ans2=check(mid+1);
            if(ans1==m&&ans2>m){R=mid;break;}
            if(ans1>m){R=r=mid-1;}
            if(ans2<=m){R=l=mid+1;}
        }
        printf("%lld %lld\n",L,R-L+1);
    }
    return 0;
}

//戒骄戒躁,继续努力!
数组越界,cnm!

posted @ 2017-10-02 13:08  Ren_Ivan  阅读(182)  评论(0编辑  收藏  举报