题目大意:给一个长度为n的序列用来表示一个只有01的字符串,a[1]表示开始有a[1]个0,a[2]表示有之后a[2]个1,a[3]表示之后又有a[3]个0...
有m个询问,每次询问给你一个ai和bi,问在原字符串中是否存在一个连续的区间,区间内的0的个数刚好为ai,1的个数刚好为bi,
有的话在最后输出答案的字符串的第i的字符是1,否则为0。
思路:要求的问题还是很清晰的,结论还是明显的,思路还是很好想的。
答案在一个连续的区间,这个连续的区间要么是在单个区间,即只有0或1的一个区间;
要么是刚好横跨了两个区间;要么是横跨了三个以上的区间,这个时候至少包含的1个或多个完整的区间;
于是我们对三种情况分别处理一下,对于每一种情况,我们可以设l为0的下界,r为0的上界,L为1的下界,R为1的上界(细节可以看代码)
然后对询问先按a排个序,如果ai刚好等于l,我们就可以把L-R这个区间更新到b的合法的区间中,如果ai刚好大于r,那在把L-R从b的合法的区间中拿出来
然后判断当前的bi是不是在合法的区间内,就好了。合法区间的更新具体实现可以用扫描线,或者树状数组水一水。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int n,m,a[1111];
char ans[maxn];//存答案最后用字符串输出,速度可能快点
int t[maxn*2];//树状数组
int A[maxn*2],Alen;//对不同的数离散化处理
struct Op
{
int pos,d;
int L,R;
bool operator < (const Op &p) const
{
return pos<p.pos;
}
}op[maxn*2],p;//存所有的操作
int oplen;
struct Q
{
int id;
int a,b;
bool operator < (const Q &q) const
{
return a<q.a;
}
}q[maxn];
int l,r;//0的数量的上下界
int L,R;//1的数量的上下界
void join()//根据l,r,L,R加入操作
{
p.d=1,p.pos=l;
p.L=L,p.R=R;
op[oplen++]=p;
p.d=-1,p.pos=r+1;
op[oplen++]=p;
A[++Alen]=L;
A[++Alen]=R;
}
void add(int pos,int d)
{
for(int i=pos;i<=Alen;i+=i&-i)
t[i]+=d;
}
int sum(int pos)
{
int ret=0;
for(int i=pos;i>0;i-=i&-i)
ret+=t[i];
return ret;
}
int main()
{
int i,j,k,T;
scanf("%d",&T);
while(T--)
{
Alen=oplen=0;
memset(a,0,sizeof(a));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
{
if(i&1)//单个区间内
l=0,r=a[i],L=R=0;
else
l=r=0,L=0,R=a[i];
join();
if(i<n)//i,i+1这两个相邻区间各取一部分
if(i&1)
l=0,r=a[i],L=0,R=a[i+1];
else
l=0,r=a[i+1],L=0,R=a[i];
join();
l=r=L=R=0;
for(j=i;j<=n;j++)//至少包含从i-j之间的区间,然后向两边最多各延伸一个区间
{
if(j&1)
{
l+=a[j];
r=l;
R=L+a[j+1];//向右延伸一个区间
}
else
{
L+=a[j];
R=L;
r=l+a[j+1];
}
if(i&1)//向左延伸一个区间
R+=a[i-1];
else
r+=a[i-1];
join();
}
}
for(i=1;i<=m;i++)
{
q[i].id=i;
scanf("%d%d",&q[i].a,&q[i].b);
A[++Alen]=q[i].b;
}
sort(q+1,q+m+1);
sort(op,op+oplen);
sort(A+1,A+Alen+1);
Alen=unique(A+1,A+Alen+1)-A;
for(i=0;i<=Alen;i++) t[i]=0;
k=0;
for(i=1;i<=m;i++)
{
for(;k<oplen && q[i].a>=op[k].pos;k++)
{
int ll=lower_bound(A+1,A+Alen,op[k].L)-A;
int rr=lower_bound(A+1,A+Alen,op[k].R)-A;
add(ll,op[k].d);
add(rr+1,op[k].d*-1);
}
int pos=lower_bound(A+1,A+Alen,q[i].b)-A;
ans[q[i].id-1]= (sum(pos)>0) + '0';
}
ans[m]=0;
printf("%s\n",ans);
}
return 0;
}
/*
768
5 5
5 5 1 5 5
11 10
6 5
7 9
6 1
5 6
3 5
5 5 5
10 5
5 5
6 5
6 6
8 4
1 5
5
3 0
5 0
7 0
5 1
3 1
2 5
5 5
3 0
0 3
3 3
5 5
6 6
*/