您的位置:首页 > 其它

LA 4108 SKYLINE 线段树

2014-01-23 18:59 246 查看
题目

对于第i个建筑物,问当前状况下能看见第i个建筑物多长的部分,然后求和.

用一个点i表示[i,i+1]这个区间,然后瞎搞

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
inline int input()
{
    int ret=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
    return ret;
}

#define N 100005
#define L t<<1
#define R t<<1|1
struct node
{
    int l,r,Min,Max,lazy;
}root[N<<2];
int t,n,l,r,h;
int ans;

inline void build(int t,int x,int y)
{
    root[t].l=x,root[t].r=y;
    root[t].Min=root[t].Max=0,root[t].lazy=-1;
    if(x!=y)
    {
        int mid=(x+y)>>1;
        build(L,x,mid),build(R,mid+1,y);
    }
}
inline void modefiy(int t,int x,int y,int h,int tag)
{
    int l=root[t].l,r=root[t].r,mid=(l+r)>>1;
    if(root[t].Min>h) return;
    if(l==r)
    {
        if(root[t].Max<=h)
        {
            if(tag)ans++;
            root[t].Max=root[t].Min=h;
        }
        return;
    }
    if(l>=x&&r<=y&&root[t].Max<=h)
    {
        root[t].Min=root[t].Max=root[t].lazy=h;
        if(tag)ans+=r-l+1;
        //printf("%d  %d %d xx\n",ans,r,l);
        return;
    }
    if(root[t].lazy!=-1)
    {
        modefiy(L,l,mid,root[t].lazy,0);
        modefiy(R,mid+1,r,root[t].lazy,0);
        root[t].lazy=-1;
    }
    if(x<=mid) modefiy(L,x,min(mid,y),h,tag);
    if(y>mid) modefiy(R,max(x,mid+1),y,h,tag);
    root[t].Min=min(root[L].Min,root[R].Min);
    root[t].Max=max(root[L].Max,root[R].Max);
}
int main()
{
    while(1)
    {
        t=input();
        if(t==0) break;
        while(t--)
        {
            n=input();
            ans=0;
            build(1,1,100000);
            for(int i=0;i<n;i++)
            {
                l=input(),r=input(),h=input();
                modefiy(1,l,r-1,h,1);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: