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\n",a==b);
        return 0;
    }
    if (a>b) puts("0");else
    printf("%lld\n",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\n",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\n",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\n",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\n",ask(1,0,n,n,n));
}
View Code

 

F结论题留坑

转载于:https://www.cnblogs.com/Enceladus/p/6915461.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值