2016 Multi-University Training Contest 2 H Helter Skelter (hdu5741) 【二分】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5741

题意:给你n个数字表示一个字符串s的压缩形式,再给你m个询问,询问是否存在一个区间是由a个0,b个1组成,是输出1,否输出0.

分析:如果我们确定了a的个数,那么b的个数就是一个区间,我们暴力将所有的可行(a,b),可以发现他们分布在一个封闭的二位平面上,我们可以找到这个二维平面的上界,下界(就是b的范围),二分a看b是否在这个区间内。xg题解

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[Mn];
int sum[Mn][2];
struct node {
    int x,y;
    node(){}
    node(int x,int y):x(x),y(y){}
}up[Mn*Mn],down[Mn*Mn];
bool cmp1(node a,node b) {
    if(a.y==b.y) return a.x>b.x;
    return a.y<b.y;
}
bool cmp2(node a,node b) {
    if(a.x==b.x) return a.y>b.y;
    return a.x<b.x;
}
int getup(int l,int r,int x) {
    while(l+1<r) {
        int mid=(l+r)>>1;
        if(up[mid].x<=x) l=mid;
        else r=mid;
    }
    return up[l].y;
}
int getdown(int l,int r,int x) {
    while(l+1<r) {
        int mid=(l+r)>>1;
        if(down[mid].x<x) l=mid;
        else r=mid;
    }
    return down[r].y;
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int n,m;
        CLR(sum,0);
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) {
            scanf("%d",&a[i]);
            sum[i][0]=sum[i-1][0];
            sum[i][1]=sum[i-1][1];
            sum[i][i&1]+=a[i];
        }
        int dcnt=0,ucnt=0;
        down[dcnt++]=node(0,0);
        for(int i=0;i<n;i++) {
            for(int j=i;j<n;j++) {
                int x=sum[j][0]-sum[i-1][0],y=sum[j][1]-sum[i-1][1];
                if((i%2==0)&&(j%2==0)) down[dcnt++]=node(x,y);
                if(i%2&&j%2) up[ucnt++]=node(x,y);
            }
        }
        sort(down+1,down+dcnt,cmp1);
        int cnt=0;
        for(int i=1;i<dcnt;i++)
            if(down[i].x>down[cnt].x) down[++cnt]=down[i];
        dcnt=cnt+1;
        sort(up,up+ucnt,cmp2);
        cnt=0;
        for(int i=1;i<ucnt;i++)
            if(up[i].y>up[cnt].y) up[++cnt]=up[i];
        ucnt=cnt+1;
        while(m--) {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x>sum[n-1][0]) {
                printf("0");
                continue;
            }
            int l=getdown(0,dcnt,x);
            int r=getup(0,ucnt,x);
            if(y>=l&&y<=r) printf("1");
            else printf("0");
        }
        printf("\n");
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值