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 unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 3e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = (int)1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

struct Line {
    LL x, y1, y2;
    bool operator < (const Line &rhs) const {
        return x < rhs.x;
    }
    int w;
};

struct Qus {
    bool operator < (const Qus &rhs) const {
        return x < rhs.x;
    }
    LL x, y, id;
};

LL hs[N], hs_cnt;

struct Bit {
    int a[N];
    void init() {
        for(int i = 1; i <= hs_cnt; i++) {
            a[i] = 0;
        }
    }
    inline void modify(int x, int v) {
        for(int i = x; i <= hs_cnt; i += i & -i) {
            a[i] += v;
        }
    }
    inline int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }
};

int n, m, mx[2], a[N], ans[N];
LL sum[2][N];

int L_cnt;
Line L[N];

int Q_cnt;
Qus Q[N];

Bit bit;

void init() {
    mx[0] = mx[1] = 0;
    L_cnt = Q_cnt = hs_cnt = 0;
}

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        init();
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            sum[0][i] = sum[0][i - 1];
            sum[1][i] = sum[1][i - 1];
            sum[!(i & 1)][i] += a[i];
            chkmax(mx[!(i & 1)], a[i]);
        }
        for(int i = 1; i <= n; i++) {
            for(int j = i + 1; j <= n; j++) {
                LL lx = 0, ly = 0, rx = 0, ry = 0;
                if(i + 1 < j) {
                    lx = sum[0][j - 1] - sum[0][i];
                    ly = sum[1][j - 1] - sum[1][i];
                }
                rx = lx; ry = ly;
                if(i & 1) rx += a[i];
                else ry += a[i];
                if(j & 1) rx += a[j];
                else ry += a[j];
                L[++L_cnt] = Line{lx, ly, ry, 1};
                L[++L_cnt] = Line{rx + 1, ly, ry, -1};
                hs[++hs_cnt] = ly;
                hs[++hs_cnt] = ry;
            }
        }
        for(int i = 1; i <= m; i++) {
            LL x, y; scanf("%lld%lld", &x, &y);
            if(!x) {
                ans[i] = mx[1] >= y;
            }
            else if(!y) {
                ans[i] = mx[0] >= x;
            }
            else {
                hs[++hs_cnt] = y;
                Q[++Q_cnt] = Qus{x, y, i};
            }
        }
        sort(hs + 1, hs + 1 + hs_cnt);
        hs_cnt = unique(hs + 1, hs + 1 + hs_cnt) - hs - 1;
        bit.init();
        for(int i = 1; i <= L_cnt; i++) {
            L[i].y1 = lower_bound(hs + 1, hs + 1 + hs_cnt, L[i].y1) - hs;
            L[i].y2 = lower_bound(hs + 1, hs + 1 + hs_cnt, L[i].y2) - hs;
        }
        for(int i = 1; i <= Q_cnt; i++) {
            Q[i].y = lower_bound(hs + 1, hs + 1 + hs_cnt, Q[i].y) - hs;
        }
        sort(L + 1, L + 1 + L_cnt);
        sort(Q + 1, Q + 1 + Q_cnt);
        for(int i = 1, j = 1; i <= Q_cnt; i++) {
            while(j <= L_cnt && L[j].x <= Q[i].x) {
                bit.modify(L[j].y1, L[j].w);
                bit.modify(L[j].y2 + 1, -L[j].w);
                j++;
            }
            ans[Q[i].id] = bit.sum(Q[i].y);
        }
        for(int i = 1;  i <= m; i++) {
            putchar(ans[i] ? ‘1‘ : ‘0‘);
        }
        puts("");
    }
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/11517157.html

时间: 2024-07-30 01:37:09

HDU - 5741 Helter Skelter 扫描线 + 树状数组的相关文章

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 con

hdu 3015 Disharmony Trees (离散化+树状数组)

Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 663    Accepted Submission(s): 307 Problem Description One day Sophia finds a very big square. There are n trees in the square. T

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

[扫描线+树状数组]解决矩形包含点的问题

今天做到第二题,大部分的思路都理解了之后最后剩下一个问题 zzx:“然后扫描线+树状数组搞一下就好了” 看到这两个算法就产生了一种我肯定会的错觉... 然后后来发现并不会的时候很惭愧... 然后十分感谢YDC,在之前完全陌生的情况下 我去问这样一个问题 超级超级超级耐心地给我解答  我问着每一个他们看起来显然的具体处理方法 突然发现真的像张老师说的:“你普及升提高的这条路没有怎么走,中间那块知识是空着的啊” 今天才切实体会到...但是或许正是这样今天学到这样的一个东西更让我觉得开心吧 树状数组解

HDU 3584 Cube (三维 树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A, whose elements are either 0 or 1. A[i, j, k] means the number in the i-th row , j-th column and k-th layer. Initially we have A[i, j, k] = 0 (1 <= i, 

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

hdu 5592 ZYB&#39;s Game 树状数组

ZYB's Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5592 Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to restore the premutation

【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

[BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black,  她觉得这个游戏太简单了,于是发明了一个更加难的版本.首先有一个地图,是一棵由 n 个顶点.n-1 条边组成的树(例如图 1给出的树包含 8 个顶点.7 条边).这颗树上有 P 个盘子,每个盘子实际上是一条路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值.第 i 个盘子

FZU 2225 小茗的魔法阵 扫描线+树状数组

这个题和一个CF上的找"Z"的题差不多,都是扫描线+树状数组 从右上角的主对角线开始扫描,一直扫到左下角,每次更新,右延伸等于该扫描线的点,注意在其所在的树状数组更新就好了 时间复杂度O(n^2logn) #include <stdio.h> #include <iostream> #include <vector> #include <math.h> #include <set> #include <map> #