您的位置:首页 > 其它

HDU 5741 Helter Skelter(二分)

2016-07-27 16:01 295 查看
Description

给出n个整数a[i]表示一个a[1]个0,a[2]个1,a[3]个0,…这样的字符串,给出m次询问,每次询问该字符串是否含有x个0和y个1的子串

Input

第一行为一整数T表示用例组数,每组用例首先输入两个整数n和m,之后n个整数a[i],最后m行每行两个整数x,y表示一次查询(1<=n<=1000,1<=m<=5*10^5,1<=a[i]<=10^6)

Output

对于每组用例,输出m个0或1表示该次查询结果

Sample Input

3

2 3

3 4

3 0

3 4

1 2

3 4

1 2 3

5 1

4 2

1 3

3 2

12 10

2 1 1 2 3 4 1 4 1 1 2 7

2 1

2 2

2 3

2 4

2 5

4 1

4 2

4 3

4 4

4 5

Sample Output

111

0101

1111101111

Solution

可以注意到对于一个固定的a, 可行的b一定是一个区间. 如果我们把所有可行的(a,b)画在二维平面上, 可以观察到一个有趣的现象: 这个可行区域一定是连通的, 且上下界有一些和x轴y轴平行的线段组成. 如下图所示.

显然, 求出这个上下边界这道题目就搞定了. 考虑求下边界, 观察上图可以知道, 求出所有红色的点就可以确定这个下边界. 同样, 所有绿色的点就可以确定上边界.



而简单分析可知所有红色的点都是以0开始,以0结束,所有绿色点都是以1开始以1结束,而且红色点和绿色点,对于相同横坐标,纵坐标非减,通过这个性质可以求出所有红色点和绿色点,对于每次查询(x,y),对红色点和绿色点分别二分搜索x即可确定y的上下界,判断y是否在上下界之间即可判断原串中是否含有x个0和y个1的子串

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1111
struct node
{
int x,y;
node(){};
node(int _x,int _y)
{
x=_x,y=_y;
}
bool operator <(const node &b)const
{
if(x!=b.x)return x<b.x;
return y<b.y;
}
}up[maxn*maxn],down[maxn*maxn];
int T,n,m,a[maxn],res1,res2;
char ans[555555];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
res1=res2=0;
for(int i=0;i<n;i++)
{
int x=0,y=0;
for(int j=i;j<n;j++)
{
if(j%2==0)x+=a[j];
else y+=a[j];
if(i%2==0&&j%2==0)down[res1++]=node(x,y);
else if(i%2==1&&j%2==1)up[res2++]=node(x,y);
}
}
sort(down,down+res1);
int cnt=0;
for(int i=0,j;i<res1;i=j)
{
for(j=i;j<res1&&down[j].x==down[i].x;j++);
while(cnt>0&&down[cnt-1].y>=down[i].y)cnt--;
down[cnt].x=down[i].x,down[cnt++].y=down[i].y;
}
res1=cnt;
sort(up,up+res2);
cnt=0;
for(int i=0,j;i<res2;i=j)
{
for(j=i;j<res2&&up[j].x==up[i].x;j++);
if(!cnt||up[j-1].y>up[cnt-1].y)up[cnt].x=up[j-1].x,up[cnt++].y=up[j-1].y;
}
res2=cnt;
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
int pos1=lower_bound(down,down+res1,node(a,-INF))-down;
int pos2=lower_bound(up,up+res2,node(a,INF))-up;
if(pos1<res1&&b>=down[pos1].y&&b<=up[pos2-1].y)ans[i]='1';
else ans[i]='0';
}
ans[m]=0;
printf("%s\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: