POJ 3277(离散化,线段树)

来源:互联网 发布:2017网络购物交易额 编辑:程序博客网 时间:2024/06/10 05:44
#include <iostream>
#include <cstdio>
#include <algorithm>
#define _(d) while(d isdigit(ch=getchar()))
#define For(i,a,b) for(int i=a;i<=b;++i) 
#define L(x) (x<<1)
#define R(x) ((x<<1)+1)
using namespace std;
const int MaxN=40005;
typedef long long LL;
int p[2*MaxN],len,lp[MaxN],rp[MaxN],h[MaxN];
inline void Get(int &x){char ch;_(!);x=ch-48;_()x=(x<<3)+x+x+ch-48;}


struct treeNode
{
    int left,right,mid,high;
}tree[8*MaxN];


inline void build(int l,int r,int num)
{
    tree[num].left=l;tree[num].right=r;
tree[num].mid=(l+r)>>1;tree[num].high=0;
if(l+1!=r)//如果不是叶子节点
{
build(l,tree[num].mid,L(num));
build(tree[num].mid,r,R(num));
}
}


inline void insert(int l,int r,int num,int i)//更新线段树 
{
    if(p[tree[num].left]==l&&p[tree[num].right]==r)//刚好覆盖                    
{                                                                               
   if(tree[num].high<h[i] ||tree[num].high==0)//原值小于插入高度或者原值为零
   tree[num].high=h[i];
return;
}
if(r<=p[tree[num].mid]) {insert(l,r,L(num),i);}//包含在线段的左半段 
else if(l>=p[tree[num].mid]) {insert(l,r,R(num),i);} //包含在线段的右半段
else//分开两半 
{
insert(l,p[tree[num].mid],L(num),i);//更新左半段 
insert(p[tree[num].mid],r,R(num),i);//更新右半段  
}
}


inline LL cal(int h,int num)
{
    if(tree[num].high<h) tree[num].high=h;
if(tree[num].left+1==tree[num].right)//叶子节点
{
   return LL(tree[num].high)*(p[tree[num].right]-p[tree[num].left]);
}
return cal(tree[num].high,L(num))+cal(tree[num].high,R(num));
}


int main()
{
    int N;
    Get(N);
    For(i,1,N)
{
   Get(lp[i]);Get(rp[i]);Get(h[i]);
p[++len]=lp[i];p[++len]=rp[i];//离散化
}
sort(p+1,p+len+1);
int M=unique(p+1,p+len+1)-p-1;//去重,M为不重复的个数
build(1,M,1);//建树 
For(i,1,N) insert(lp[i],rp[i],1,i); //插入高度,即每棵树的权值
LL ans=cal(0,1);//计算答案
printf("%lld\n",ans);
    return 0;
}
0 0