sdut2610---Boring Counting(离线+树状数组+离散化)

Boring Counting

Time Limit: 3000ms Memory limit: 65536K 有疑问?点这里^_^

题目描述

In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence. Now you task is to answer a list of queries, for each query, please tell us among [L, R], how many Pi is not less than A and not greater than B( L<= i <= R). In other words, your task is to count the number of Pi (L <= i <= R, A <= Pi <= B).

输入

In the first line there is an integer T (1 < T <= 50), indicates the number of test cases.

For each case, the first line contains two numbers N and M (1 <= N, M <= 50000), the size of sequence P, the number of queries. The second line contains N numbers Pi(1 <= Pi <= 10^9), the number sequence P. Then there are M lines, each line contains four number L, R, A, B(1 <= L, R <= n, 1 <= A, B <= 10^9)

输出

For each case, at first output a line ‘Case #c:’, c is the case number start from 1. Then for each query output a line contains the answer.

示例输入

1

13 5

6 9 5 2 3 6 8 7 3 2 5 1 4

1 13 1 10

1 13 3 6

3 6 3 6

2 8 2 8

1 9 1 9

示例输出

Case #1:

13

7

3

6

9

提示

来源

2013年山东省第四届ACM大学生程序设计竞赛

先把数据离散化,然后离线,树状数组处理

/*************************************************************************
    > File Name: H.cpp
    > Author: ALex
    > Mail: [email protected]
    > Created Time: 2015年04月06日 星期一 16时35分42秒
 ************************************************************************/

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>

using namespace std;

const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

const int N = 50010;
int arr[N];
int ans[N];
struct QUE
{
    int a, b;
    int Id;
    int flag;
    QUE(int _a = 0, int _b = 0, int _Id = 0, int _flag = 0)
    {
        a = _a; b = _b; Id = _Id; flag = _flag;
    }
};

vector <QUE> que[N];

int xis[N];
int tree[N];
int cnt, n;

int search(int val)
{
    int mid;
    int l = 1, r = cnt;
    while (l <= r)
    {
        mid = (l + r) >> 1;
        if (xis[mid] > val)
        {
            r = mid - 1;
        }
        else if (xis[mid] < val)
        {
            l = mid + 1;
        }
        else
        {
            break;
        }
    }
    return mid;
}

int lowbit(int x)
{
    return x & (-x);
}

void add(int x)
{
    for (int i = x; i < N; i += lowbit(i))
    {
        ++tree[i];
    }
}

int sum(int x)
{
    int ans = 0;
    for (int i = x; i; i -= lowbit(i))
    {
        ans += tree[i];
    }
    return ans;
}

int main()
{
    int t;
    scanf("%d", &t);
    int icase = 1;
    while (t--)
    {
        int m;
        scanf("%d%d", &n, &m);
        memset(tree, 0, sizeof(tree));
        cnt = 0;
        for (int i = 1; i <= n; ++i)
        {
            que[i].clear();
            scanf("%d", &arr[i]);
            xis[++cnt] = arr[i];
        }
        int l, r, a, b;
        for (int i = 1; i <= m; ++i)
        {
            scanf("%d%d%d%d", &l, &r, &a, &b);
            que[r].push_back(QUE(a, b, i, 1));
            que[l - 1].push_back(QUE(a, b, i, -1));
        }
        memset(ans, 0, sizeof(ans));
        sort(xis + 1, xis + 1 + cnt);
        cnt = unique (xis + 1, xis + 1 + cnt) - xis - 1;
        for (int i = 1; i <= n; ++i)
        {
            int val = search(arr[i]);
            add(val);
            int size = que[i].size();
            for (int j = 0; j < size; ++j)
            {
                int a = lower_bound(xis + 1, xis + 1 + cnt, que[i][j].a) - xis;
                int b = lower_bound(xis + 1, xis + 1 + cnt, que[i][j].b) - xis;
                if (a > cnt)
                {
                    continue;
                }
                --a;
                if (b > cnt)
                {
                    b = cnt;
                }
                else if (xis[b] > que[i][j].b)
                {
                    --b;
                }
                int flag = que[i][j].flag;
                int Id = que[i][j].Id;
                ans[Id] += flag * (sum(b) - sum(a));
            }
        }
        printf("Case #%d:\n", icase++);
        for (int i = 1; i <= m; ++i)
        {
            printf("%d\n", ans[i]);
        }
    }
    return 0;
}
时间: 2024-10-29 22:17:02

sdut2610---Boring Counting(离线+树状数组+离散化)的相关文章

BZOJ 1227 [SDOI2009] 虔诚的墓主人 离线+树状数组+离散化

鸣谢:140142耐心讲解缕清了我的思路 题意:由于调这道题调的头昏脑涨,所以题意自己搜吧,懒得说. 方法:离线+树状数组+离散化 解析:首先深表本蒟蒻对出题人的敬(bi)意(shi).这道题简直丧心病狂,看完题后大脑一片空白,整个人都不好了,刚开始的思路是什么呢?暴力思想枚举每个墓碑,然后计算每个墓碑的虔诚度,然后再来统计.不过看看数据范围呢?10^9*10^9的矩阵,最多才10^5个树,光枚举就已经超时了,所以肯定不行.(不过要是考试真没思路我就那么搞了- -!) 然后也想到来枚举墓碑,不过

HDU 4358 Boring counting(树状数组)

题意:  给定一棵树,每个节点有一个点权,然后有一些询问,求以某个点为根的子树中有多少的数出现了恰好k次. 思路: 首先dfs一次将树形结构转化成线性结构,利用时间戳记录下以结点u为根的子树在数组中的开始位置和结束位置. 那么我们将所有查询记录下来离线来做,将所有的查询按右端点升序排序. 考虑用树状数组来做这道题,每个位置记录当前从1到当前位置有多少数出现了恰好k次. 从头遍历一遍数组,map离散化记录每个值出现的位置,对于每个位置,如果值出现的次数t大于k,那么在将第t-k次出现的位置加一

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

TOJ 4105 Lines Counting(离线树状数组)

4105.   Lines Counting Time Limit: 2.0 Seconds   Memory Limit: 150000K Total Runs: 152   Accepted Runs: 47 On the number axis, there are N lines. The two endpoints L and R of each line are integer. Give you M queries, each query contains two interval

POJ 3416 Crossing --离线+树状数组

题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少. 解法:离线树状数组.点不在坐标轴上,即点不共线使这题简单了不少,可以离散化点,也可以不离散化,因为x,y <= 500000,直接就可以搞.我这里是离散的,其实也没比直接搞快. 见两个树状数组,一个先把所有点都modify进去,一个等待以后加元素. 然后将查询和给出的点都按y坐标排序,然后离线对

区间的关系的计数 HDU 4638 离线+树状数组

题目大意:给你n个人,每个人都有一个id,有m个询问,每次询问一个区间[l,r],问该区间内部有多少的id是连续的(单独的也算是一个) 思路:做了那么多离线+树状数组的题目,感觉这种东西就是一个模板了,23333,反正都是定义右区间的. 这题的关键难度就是如何定义id是连续的呢.我们每次往区间里面放一个数值以后都要add(pos, 1),就是把pos~n的所有的关系都+1.然后如果说在pos之前就出现id-1,就要add(pos[id-1], -1)(同理id+1也是这样),这样子表示从pos[

HDU 5156 - Harry and Christmas tree (dfs序+离线树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=5156 BC#25的C题. 题意是:给出一颗大小为n的树,以1为根,然后给出m次染色,每次将节点u加上一种颜色(一个节点可以有多个颜色). 最后查询树上每个节点对应子树上包含的不同颜色数量. 当时这场比赛没有做,回来看一下题目,没看标解就试着敲了一遍,于是解题思路从一开始就走上了不归路. 标解是O(n+m)的方法,主要思路是将问题转为:一次染色表示将u到根节点的路径都染上这种颜色. 但这样做需要去重,因为如果u

hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球到达某个节点上,如果x==wi,那么球停在这个节点上 .当然,这个点是叶子节点也会停止 . 如果x<wi,那么有1/2的概率走向左子树,有1/2的概率走向右子树 . 如果x>wi,那么有1/8的概率走向左子树,有7/8的概率走向右子树 . 问球经过v节点的概率 .(停在v节点也算) 解法: 在线的话每一个节点建一棵根节点到该节点的线段树,离线的话就先

hdu 4417 Super Mario(离线树状数组|划分树)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2584    Accepted Submission(s): 1252 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping a