Boring Counting——【SDUT2610】主席树

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大学生程序设计竞赛

第一次敲主席树,之前感觉主席树好高大上,现在自己认真的去实现的时候会发现主席树很有趣。主席树的介绍在网上已经由很多了,不在介绍,直接上代码,或许代码中的注释会更加的清楚。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
#include <iostream>

using namespace std;

typedef long long LL;

const int Max = 1e5;

typedef struct node
{
    int l,r;

    int data;
}Tree;

Tree Tr[Max*10];

int num[Max],srt[Max];

int root[Max];

int top;

int Creat()
{
    Tr[top].l = Tr[top].r = -1;

    Tr[top].data = 0 ;

    return top++ ;
}

int BS(int *a, int L, int R, int goal) //二分
{
    int ans = -1;

    while(L<=R)
    {
        int mid = (L+R) >> 1;

        if(a[mid] == goal) return mid;

        if(a[mid]<goal) L=mid+1,ans = mid;

        else R =  mid-1;
    }
    return ans;
}

void Init(int &fa,int l,int r)//初始化,建立0状态时的线段树。
{
    fa = Creat();

    if(l == r) return ;

    int mid = (l+r) >> 1;

    Init(Tr[fa].l,l,mid);

    Init(Tr[fa].r,mid+1,r);
}

void Update(int pre,int now,int l,int r,int goal)//更新其他的状态
{
    if(l == r) 
    {
        Tr[now].data = Tr[pre].data+1;

        return ;
    }

    int mid = (l + r) >> 1;

    if(goal <= mid)
    {
        Tr[now].r = Tr[pre].r;

        Tr[now].l = Creat();

        Update(Tr[pre].l,Tr[now].l,l,mid,goal);
    }
    else 
    {
        Tr[now].l = Tr[pre].l;

        Tr[now].r = Creat();

        Update(Tr[pre].r,Tr[now].r,mid+1,r,goal);
    }

    Tr[now].data = Tr[Tr[now].l].data+Tr[Tr[now].r].data;
}

int Query(int now,int l,int r ,int goal)//查询在[0,now]的区间中的<= goal 的数的数量
{
    if(goal==-1)
    {
        return 0;
    }

    if(r==goal)
    {
        return Tr[now].data;
    }

    int mid = (l + r) >> 1;

    if(mid < goal) return Tr[Tr[now].l].data+Query(Tr[now].r,mid+1,r,goal);

    else return Query(Tr[now].l, l, mid, goal);

}

int main()
{
    int T,z = 1;

    int n,m;

    scanf("%d",&T);

    while(T--)
    {
        scanf("%d %d",&n,&m);

        for(int i = 1 ; i <= n;i++)
        {
            scanf("%d",&num[i]);

            srt[i] = num[i];
        }

        sort(srt+1, srt + n + 1);

        int N = 1;

        for(int i = 2;i <= n; i++)//离散化
        {
            if(srt[i] != srt[N]) srt[++N] = srt[i];
        }

        for(int i = 1;i<=n;i++)
        {
            num[i] = BS(srt,1,N,num[i]);

        }

        root[0] = -1;

        top = 0;

        Init(root[0],1,N);//初始化主席树

        for(int i = 1;i<=n;i++)//更新状态
        {
            root[i] = Creat();

            Update(root[i-1],root[i],1,N,num[i]);
        }

        int l,r,Mi,Ma;

        printf("Case #%d:\n",z++);

        while(m--)
        {
            scanf("%d %d %d %d",&l,&r,&Mi,&Ma);

            if(l>r||Mi>Ma)
            {
                printf("0\n");

                continue;
            }

            Mi = BS(srt,1,N,Mi-1);//找到所要查询的区间

            Ma = BS(srt,1,N,Ma);


            printf("%d\n",Query(root[r],1,N,Ma)-Query(root[r],1,N,Mi)-Query(root[l-1],1,N,Ma)+Query(root[l-1],1,N,Mi));
        }
    }
    return 0;
}

你可能感兴趣的:(Boring Counting——【SDUT2610】主席树)