• AtCoder Grand Contest 015


    传送门

    A - A+...+B Problem

    题意:n个数最大值a,最小值b,求和的可能数量。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
     
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    int n,a,b;
    int main(){
        n=read();a=read();b=read();
        if (n==1){
            printf("%d
    ",a==b);
            return 0;
        }
        if (a>b) puts("0");else
        printf("%lld
    ",1LL*(b-a)*(n-2)+1);
    }
    View Code

    B - Evilator

    题意:一个电梯,每层只能上或下,问任意两个楼层相互抵达的操作次数之和。保证两两可达。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MN 110000
    using namespace std;
     
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    char s[MN];
    long long mmh,n;
    int main(){
        scanf("%s",s);
        n=strlen(s);mmh=(n-1)*n;
        for (int i=0;i<n;i++){
            if (s[i]=='U') mmh+=i;else mmh+=n-i-1;
        }
        printf("%lld
    ",mmh);
    }
    View Code

    C - Nuske vs Phantom Thnook

    题意:一个有障碍的地图上,任意两个空地之间至多有一条路,每次询问一个矩形内空地的联通块个数(类似apio2017 T1)

    题解:统计矩形内空地数量,满足两端都是空地的边的数量相减即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MN 2100
    using namespace std;
     
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    int n,m,Q,q[MN][MN],w[MN][MN],d[MN][MN],map[MN][MN],x,y,X,Y;
    char s[MN];
    int main(){
        int i,j;
        n=read();m=read();Q=read();
        for (i=1;i<=n;i++){
            scanf("%s",s+1);
            for (j=1;j<=m;j++)
            map[i][j]=s[j]=='1',q[i][j]=q[i-1][j]+q[i][j-1]-q[i-1][j-1]+map[i][j];
        }
        
        for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
        w[i][j]=w[i-1][j]+w[i][j-1]-w[i-1][j-1]+(map[i][j]&&map[i][j-1]),
        d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+(map[i][j]&&map[i-1][j]);
        
        while (Q--){
            x=read();y=read();X=read();Y=read();
            printf("%d
    ",q[X][Y]-q[x-1][Y]-q[X][y-1]+q[x-1][y-1]-(w[X][Y]-w[X][y]-w[x-1][Y]+w[x-1][y])-(d[X][Y]-d[X][y-1]-d[x][Y]+d[x][y-1]));
        }
    }
    View Code

    D - A or...or B Problem

    题意:给一个区间,问有多少个数能用区间内的数进行or操作得到。

    题解:找到l与r最高的不同位(l<2^a<=r),将2^a或上[l,2^a-1]是有贡献的,再递归处理[2^a,r]区间内贡献即可。

    比赛结束一分钟过D题样例……

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MN 2100
    #define ll long long
    using namespace std;
     
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    long long l,r,mmh;
    inline ll max(ll a,ll b){return a>b?a:b;}
    inline ll min(ll a,ll b){return a<b?a:b;}
    inline ll work(ll l,ll r,ll up){
        if (l>r) swap(l,r);
        int i;
        if (l==r) return 0;
        for (i=60;;i--) if (((r>>i)&1)&&(!((l>>i)&1))) break;
        r&=(1ll<<(i+1))-1;l&=(1ll<<(i+1))-1;r^=1ll<<i;up^=1ll<<i;
        if (r+1>=l) return min(1ll<<i,up)-r-1;
        ll mmh=work(1,r,l);
        mmh+=min((1ll<<i),up)-l;
        return mmh;
    }
    int main(){
        int i,j;
        scanf("%lld%lld",&l,&r);
        if (l==r) return puts("1"),0;
        printf("%lld
    ",work(l,r,1ll<<62)+r-l+1);
    }
    View Code

    E - Mr.Aoki Incubator

    题意:数轴上一些质点,有初始位置和速度,初始时选定一些点染色,运动过程中质点相遇可以相互染色(已染的染到未染的上面),问多少种方式能使足够长时间后所有点都被染色。

    题解:赛后看题解才会系列……将所有点按速度排序,对于每个点i找出初始坐标小于它的速度最大的点R和初始坐标大于它的速度最小的点L,那么染上点i后,最终[L,R]内的点都会被染上。证明其实很显然,对于(i,R)中的点,如果初始坐标大于i,那会在R碰到i被染上以后被R染上,如果初始坐标小于i,那它自己会碰到i。(L,i)中的点同理。然后用线段树优化一下DP即可。

    #include<cstdio>
    #include<algorithm>
    #define MN 200001
    #define lp p<<1
    #define rp p<<1|1
    using namespace std;
    
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    const int MOD=1e9+7;
    inline void M(int &x){while(x>=MOD)x-=MOD;}
    inline int _M(int x){M(x);return x;}
    struct tree{int p,s,c;tree(){c=1;}}t[MN*20];
    struct na{int l,r;}w[MN];
    struct ma{int x,v;}a[MN];
    bool operator < (ma a,ma b){return a.v<b.v;}
    bool operator < (na a,na b){return a.l<b.l;}
    int n,m,stl[MN][20],str[MN][20];
    inline int max(int a,int b){return a>b?a:b;}
    inline int min(int a,int b){return a<b?a:b;}
    void hb(int p,int c){
        t[p].c=1LL*t[p].c*c%MOD;
        t[p].s=1LL*t[p].s*c%MOD;
    }
    void pd(int p){if (t[p].c!=1) hb(lp,t[p].c),hb(rp,t[p].c),t[p].c=1;}
    void gx(int p){M(t[p].s=t[lp].s+t[rp].s);}
    void add(int p,int l,int r,int k,int v){
        if (l==r){
            M(t[p].s+=v);
            return;
        }
        if (l!=r) pd(p);
        int mid=l+r>>1;
        if (k<=mid) add(lp,l,mid,k,v);else add(rp,mid+1,r,k,v);
        gx(p);
    }
    int ask(int p,int l,int r,int L,int R){
        if (l>=L&&r<=R) return t[p].s;
        pd(p);
        int mid=l+r>>1;
        if (R<=mid) return ask(lp,l,mid,L,R);else
        if (L>mid) return ask(rp,mid+1,r,L,R);else
        return _M(ask(lp,l,mid,L,R)+ask(rp,mid+1,r,L,R));
    }
    void cc(int p,int l,int r,int k){
        if (l>=k) hb(p,2);else{
            pd(p);
            int mid=l+r>>1;
            if (k>mid) cc(rp,mid+1,r,k);else cc(lp,l,mid,k),cc(rp,mid+1,r,k);
            gx(p);
        }
    }
    int main(){
        int i,j;
        n=read();
        for (i=1;i<=n;i++) a[i].x=read(),a[i].v=read();
        sort(a+1,a+1+n);
        for (i=1;i<=n;i++) for (stl[i][0]=a[i].x,j=1;j<20&&(i>>j);j++) stl[i][j]=min(stl[i][j-1],stl[i-(1<<(j-1))][j-1]);
        for (i=n;i>=1;i--) for (str[i][0]=a[i].x,j=1;j<20&&i+(1<<j)-1<=n;j++) str[i][j]=max(str[i][j-1],str[i+(1<<(j-1))][j-1]);
        
        for (i=1;i<=n;i++){
            int l=1,r=n;
            for (j=19;j>=0;j--) if (str[l][j]&&str[l][j]<a[i].x) l+=1<<j;
            for (j=19;j>=0;j--) if (stl[r][j]&&stl[r][j]>a[i].x) r-=1<<j;
            w[i].l=l;w[i].r=r;
        }
        
        sort(w+1,w+1+n);
        add(1,0,n,0,1);
        for (i=1;i<=n;i++){
            cc(1,0,n,w[i].r);
            add(1,0,n,w[i].r,ask(1,0,n,w[i].l-1,w[i].r-1));
        }
        printf("%d
    ",ask(1,0,n,n,n));
    }
    View Code

    F结论题留坑

  • 相关阅读:
    C++ primer plus读书笔记——第16章 string类和标准模板库
    C++ primer plus读书笔记——第15章 友元、异常和其他
    C++ primer plus读书笔记——第14章 C++中的代码重用
    C++ primer plus读书笔记——第13章 类继承
    C++ primer plus读书笔记——第12章 类和动态内存分配
    开发中常用的一些神器推荐
    收集常用的Linux常用命令
    【数据库】13种会导致索引失效语句写法
    Windows终端利器Cmder
    嵌入式操作系统的主要特点都有哪些
  • 原文地址:https://www.cnblogs.com/Enceladus/p/6915461.html
Copyright © 2020-2023  润新知