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

HDU 5372 线段树

时间:2015-08-12 17:01:05      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:

给出两种操作:

第i个0:在x位置插入一个长度为i的线段,并输出该线段共覆盖了多少之前加入的线段

1:删除第i次插入的线段

官方题解:对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点。 再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案。用两个树状数组搞定。时间复杂度nlog


思路很好理解,直接用一个线段树记录区间的左端点和右端点即可

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
const int inf=0x7fffffff;
struct A
{
    int op,l,r,x;
} a[400010];

struct Y
{
    int x,id;
} y[400010];

struct Data
{
    int l,r,a,b;
} data[1600010];

bool cmp(Y a,Y b)
{
    return a.x<b.x;
}

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

    int mid=(l+r)/2;

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

int query(int l,int r,int k,int op)
{
    if (l>r) return 0;
    if (data[k].l==l && data[k].r==r)
    {
        if (op==1) return data[k].a;
        else return data[k].b;
    }

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

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

void updata(int n,int k,int op,int x)
{
    if (op==1) data[k].a+=x;
    else data[k].b+=x;

    if (data[k].l==n && data[k].r==n) return ;

    if (n<=data[k*2].r) updata(n,k*2,op,x);
    else updata(n,k*2+1,op,x);
}

int main()
{
    int Case,n,i,x,cnt;
    Case=1;
    while (scanf("%d",&n)!=EOF)
    {
        cnt=1;

        for (i=0; i<n; i++)
        {
            scanf("%d",&a[i].op);
            if (a[i].op==0)
            {
                scanf("%d",&a[i].l);
                a[i].r=a[i].l+cnt;
                cnt++;
            }
            else
            {
                scanf("%d",&x);
                x--;
                a[i].x=x;
            }
            y[i*2].x=a[i].l;
            y[i*2].id=-i-1;
            y[i*2+1].x=a[i].r;
            y[i*2+1].id=i+1;

        }
        sort(y,y+n*2,cmp);
        cnt=0;
        if (y[0].id<0)
            a[-y[0].id-1].l=0;
        else
            a[y[0].id-1].r=0;

        for (i=1; i<n*2; i++)
        {
            if (y[i].x!=y[i-1].x) cnt++;
            if (y[i].id<0) a[-y[i].id-1].l=cnt;
            else a[y[i].id-1].r=cnt;
        }

        build(0,cnt,1);

        printf("Case #%d:\n",Case++);
        int temp=0;
        for (i=0; i<n; i++)
        {
            if (a[i].op==0)
            {
                printf("%d\n",query(a[i].l,cnt,1,1)-query(a[i].r+1,cnt,1,2));
                updata(a[i].l,1,1,1);
                updata(a[i].r,1,2,1);
                a[temp].l=a[i].l;
                a[temp].r=a[i].r;
                temp++;
            }
            else
            {
                updata(a[a[i].x].l,1,1,-1);
                updata(a[a[i].x].r,1,2,-1);
            }

        }
    }

    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 5372 线段树

标签:

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

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