hdu 5741 Helter Skelter(扫描线)

题目链接:hdu 5741 Helter Skelter

题意:

给定一个二进制的字符串,有 M次询问 
问是否存在含有 a个 0 ,b个 1的区间

题解:

我们可以n2处理出每个区间,然后我们可以发现每个区间是一个矩形。

现在问题就转换成了有多少个点在这些矩形内。

然后就可以离散化后扫描线一下。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4
 5 const int N=2e6+7;
 6
 7 struct node
 8 {
 9     int op,x,a,b;
10     node(int _a=0,int _b=0,int _c=0,int _d=0):op(_a),x(_b),a(_c),b(_d){}
11     bool operator <(const node &B)const{return x!=B.x?x<B.x:op<B.op;}
12 }A[N];
13
14 int t,n,m,x,y,a[2000],ed,cnt[2],tp[2];
15 int hsh[N*2],h_ed,C[N];
16 char ans[N];
17
18 inline void add(int x,int c){while(x<=h_ed)C[x]+=c,x+=x&-x;}
19 inline int ask(int x){int an=0;while(x)an+=C[x],x-=x&-x;return an;}
20 int idx(int x){return lower_bound(hsh+1,hsh+1+h_ed,x)-hsh;}
21
22
23 int main(){
24     scanf("%d",&t);
25     while(t--)
26     {
27         ed=0,scanf("%d%d",&n,&m);
28         F(i,1,n)scanf("%d",a+i);
29         F(i,1,n)
30         {
31             cnt[0]=cnt[1]=0;
32             cnt[!(i&1)]+=a[i];
33             tp[0]=tp[1]=0;
34             tp[!(i&1)]+=a[i];
35             A[++ed]=node(-1,cnt[0]-tp[0],cnt[1]-tp[1],cnt[1]);
36             A[++ed]=node(1,cnt[0],cnt[1]-tp[1],cnt[1]);
37             F(j,i+1,n)
38             {
39                 cnt[!(j&1)]+=a[j];
40                 tp[0]=tp[1]=0;
41                 tp[!(i&1)]+=a[i];
42                 tp[!(j&1)]+=a[j];
43                 A[++ed]=node(-1,cnt[0]-tp[0],cnt[1]-tp[1],cnt[1]);
44                 A[++ed]=node(1,cnt[0],cnt[1]-tp[1],cnt[1]);
45             }
46         }
47         F(i,1,m)
48         {
49             scanf("%d%d",&x,&y);
50             A[++ed]=node(0,x,y,i);
51         }
52         sort(A+1,A+1+ed),h_ed=0;
53         F(i,1,ed)
54         {
55             if(A[i].op!=0)hsh[++h_ed]=A[i].a,hsh[++h_ed]=A[i].b;
56             else hsh[++h_ed]=A[i].a;
57         }
58         sort(hsh+1,hsh+1+h_ed),h_ed=unique(hsh+1,hsh+1+h_ed)-hsh-1;
59         F(i,1,ed)
60         {
61             if(A[i].op!=0)A[i].a=idx(A[i].a),A[i].b=idx(A[i].b);
62             else A[i].a=idx(A[i].a);
63         }
64         F(i,1,ed)
65         {
66             if(A[i].op)
67             {
68                 add(A[i].a,-1*A[i].op);
69                 add(A[i].b+1,A[i].op);
70             }else
71             {
72                 int now=ask(A[i].a);
73                 ans[A[i].b]=(now!=0)+‘0‘;
74             }
75         }
76         ans[m+1]=0;
77         printf("%s\n",ans+1);
78         F(i,0,h_ed)C[i]=0;
79     }
80     return 0;
81 }

时间: 2024-08-08 01:30:49

hdu 5741 Helter Skelter(扫描线)的相关文章

HDU - 5741 Helter Skelter 扫描线 + 树状数组

HDU - 5741 我们枚举段的起点和终点, 那么每一种情况0的范围是[lx, rx], 1的出现范围是[ly, ry], 可以在二维平面上用矩形表示. 然后问题就变成了询问点有没有被至少一个矩形覆盖, 扫描线 + 树状数组就可以了. #pragma GCC optimize(2) #pragma GCC optimize(3) #include<bits/stdc++.h> #define LL long long #define LD long double #define ull un

HDU 5741 Helter Skelter(构造法)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5741 [题目大意] 一个01相间的串,以0开头,给出的序列每个数字表示连续的0的个数或者1的个数,现在有m个询问,求0的个数为a且1的个数为b的串是否存在. [题解] 我们发现形如11001这样子以1为开头结尾的串是包含1001这样子的串的,同理以0为开头结尾的串也是包含了一些开头结尾数字相同的子串. 可以发现,当0的个数固定,1的个数是数轴上的一个区间,而且在0的个数相差1时,必定可以取到相同

HDU 5741 Helter Skelter

离线处理+扫描线.题意很容易转化:若干个矩形形成并集,询问一些点是否在并集中? 官方题解不是这样做的....那种做法效率更高,暂时还不会.我这样是4500ms G++过的,C++TLE...... 区间加上某值,询问单点值,可以用树状数组.用线段树可能常数较大导致TLE. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #incl

[HDU 4419] Colourful Rectangle (扫描线 矩形面积并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419 题目大意:比矩形面积并多了颜色,问染成的每种颜色的面积. 矩形面积并的扫描线维护的是长度,这道题就是维护每个颜色的长度,写起来很蛋疼. 1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6

POJ 1177 &amp; HDU 1828 Picture(扫描线 + 求周长)

题目链接: POJ:http://poj.org/problem?id=1177 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1828 几个不错的讲解: http://www.cnblogs.com/scau20110726/archive/2013/04/13/3018702.html http://blog.csdn.net/xingyeyongheng/article/details/8931410 Description A number

hdu 1255(线段树 扫描线) 覆盖的面积

http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所有的横坐标和纵坐标排序 因为是从左到右扫描,那么横坐标应该离散化一下 当扫描线依次扫描的时候,依次扫描到的纵区间在线段树中查找,依据是上边还是下边记录,上边就是-1,下边就是+1, 如果某区间记录值为0的时候,代表没有被覆盖,为1的时候代表覆盖一次,为2代表覆盖两次(不会出现为负数的情况) 最后将依

HDU - 5770 Treasure 思维 + 扫描线 + 线段树 (看题解)

HDU - 5770 没想出来, 感觉不应该啊, 没有想到转换成二维上的点的问题. 对于对钥匙和宝藏(u, v), 如果lca != u && lca != v 那么起点从u子树出发, 终点在v子树就能得到贡献. 子树在dfs序下是连续一段, 所以就对应到二维平面一个矩形加上一个数值, 求值最大的点. 对于lca == u || lca == v同样可以讨论出来. 还有一种情况就是u == v, 我们先把贡献都加上, 然后对于不经过u 的所有路径进去这个贡献. 然后扫描线扫一遍就好了. #

(中等) HDU 1542 Atlantis,扫描线。

Problem Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. You

hdu 1542 线段树+扫描线

啦啦啦~继续学算法 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7349    Accepted Submission(s): 3231 Problem Description There are several