码迷,mamicode.com
首页 > 其他好文 > 详细

2013山东省赛Boring Counting 离线线段树

时间:2015-04-14 11:14:16      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

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


n个数,m次询问

每次询问在 l-r区间内的  大小范围的在 a-b之间的数字个数

先将原数组排序

做两遍线段树

第一次对m次询问的b升序排列,每次插入所有小于等于b的数字,然后线段树查询在区间 l-r范围内的数字个数,记录在ans[i].r

第二次对m次询问的a升序排列,每次插入所有小于a的数字,然后线段树查询在区间l-r范围内的数字个数,记录在ans[i].l

最后每次询问的答案即为 ans[i].r-ans[i].l;


#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;

struct A
{
    int x,id;
}a[50010];

struct B
{
    int l,r,a,b,id;
}b[50010];

struct node
{
    int l,r,x;
}data[200010];

struct Ans
{
    int l,r;
}ans[50010];

bool cmp_a(A a,A b)
{
    return a.x<b.x;
}

bool cmp_bb(B a,B b)
{
    return a.b<b.b;
}

bool cmp_ba(B a,B b)
{
    return a.a<b.a;
}

void build(int l,int r,int k)
{
    int mid;
    data[k].l=l;
    data[k].r=r;
    data[k].x=0;
    if (l==r) return ;

    mid=(l+r)/2;
    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
}

void updata(int x,int k)
{
    data[k].x++;
    if (data[k].l==data[k].r) return ;
    if (x<=data[k*2].r)
        updata(x,k*2);
    else
        updata(x,k*2+1);
}

int query(int l,int r,int k)
{
    int mid;
    if (data[k].l==l && data[k].r==r)
        return data[k].x;

    mid=(data[k].l+data[k].r)/2;

    if (r<=mid)
        return query(l,r,k*2);
    else
    if (l>mid)
        return query(l,r,k*2+1);
    else
        return query(l,mid,k*2)+query(mid+1,r,k*2+1);
}

int main()
{
    int t,Case,n,m,i,mark;
    scanf("%d",&t);
    Case=1;
    while (t--)
    {
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++)
        {
            scanf("%d",&a[i].x);
            a[i].id=i;
        }
        sort(a+1,a+1+n,cmp_a);
        a[n+1].x=1000000001;
        for (i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&b[i].l,&b[i].r,&b[i].a,&b[i].b);
            b[i].id=i;
        }

        build(1,n,1);
        sort(b+1,b+1+m,cmp_bb);
        mark=1;
        for (i=1;i<=m;i++)
        {
            while (a[mark].x<=b[i].b)
                updata(a[mark++].id,1);
            ans[b[i].id].r=query(b[i].l,b[i].r,1);
        }

        build(1,n,1);
        sort(b+1,b+1+m,cmp_ba);
        mark=1;
        for (i=1;i<=m;i++)
        {
            while (a[mark].x<b[i].a)
                updata(a[mark++].id,1);
            ans[b[i].id].l=query(b[i].l,b[i].r,1);
        }

        printf("Case #%d:\n",Case++);
        for (i=1;i<=m;i++)
            printf("%d\n",ans[i].r-ans[i].l);
    }
    return 0;
}





2013山东省赛Boring Counting 离线线段树

标签:

原文地址:http://blog.csdn.net/u011932355/article/details/45038345

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!