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
给出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; }
相关文章推荐
- centos6 安装phpredis扩展
- java多线程 sleep()和wait()的区别
- 全排列与next_permutation
- DecimalFormat类的使用
- Git入门(10)-添加远程仓库
- 平滑效果
- The Zen of Python
- swift - 各种手势用法大全
- android连接本地tomcat服务器,报timeout
- 中国互联网技术联盟发布首个“互联网+”企业评测标准
- Cocos2dx C++与Lua合并开发的VS配置环境搭建
- 条件编译
- BZOJ1019: [SHOI2008]汉诺塔
- Android样式的开发:shape篇
- 高手速成android开源项目【View篇】
- html5中canvas绘制矩形
- WKWebView加载Html文件,如何自适应网页内容呢?就是不要让它左右滑动
- 安卓项目常用的一些开源框架
- SSDP协议
- 导航菜单栏