雨へ痕
下一站路口,未知的道路

这道题本身并不难,也是线段树类型的,固定了水平面,只需要一维线段树(也只会一维 = =)线段树插入高度作为点的权值。。。

//1900ms

#include <stdio.h>
#include <stdlib.h>
#define N 40001
int a[N][3];
int top=-1;
int set[2*N];
int settop=-1;
int rset[2*N];
int rsettop=-1;
long long sum=0;
struct st{
 int a,b;
 int ld,rd;
 int high;
 int mid;
}tree[4*N];
void build(int a,int b)
{
 int mid;
 int top2;
 tree[++top].a=a;
 tree[top].b=b;
 tree[top].high=0;
 if(a==b-1) {
  tree[top].ld=-1;
  tree[top].rd=-1;
  return ;
 }
 tree[top].mid=mid=(a+b)/2;
 top2=top;
 tree[top2].ld=top+1;
 build(a,mid);
 tree[top2].rd=top+1;
 build(mid,b);
}
  
void insert(int p,int q,int c,int k)
{
 if(tree[tree[k].rd].high==tree[tree[k].ld].high && tree[tree[k].ld].high>tree[k].high )
 tree[k].high=tree[tree[k].ld].high;
 if(rset[tree[k].a]==p && rset[tree[k].b]==q && tree[k].high!=-1)  {tree[k].high=tree[k].high>c?tree[k].high:c; return ;}
 if(tree[k].high>0)
 {
    insert(rset[tree[k].a],rset[tree[k].mid],tree[k].high,tree[k].ld);
    insert(rset[tree[k].mid],rset[tree[k].b],tree[k].high,tree[k].rd);
 }
 tree[k].high=-1;
    if(p<rset[tree[k].mid] && q>rset[tree[k].mid]) 
 {insert(p,rset[tree[k].mid],c,tree[k].ld);insert(rset[tree[k].mid],q,c,tree[k].rd);}
 else if(p<rset[tree[k].mid]) insert(p,q,c,tree[k].ld);
 else insert(p,q,c,tree[k].rd);
}
  
void dfs(int k)
{
 if(!tree[k].high) return ;
 if(tree[k].high!=-1)
 {
  sum+=(rset[tree[k].b]-rset[tree[k].a])*(long long)tree[k].high;
 }
 else
 {
  dfs(tree[k].ld);
  dfs(tree[k].rd);
 }
}


int cmp(const void *a, const void *b)
{
    return(*(int *)a-*(int *)b);
}

int main()
{
 int i;
 int n;
 int p,q,c;
 int temp;
// freopen("1.txt", "r", stdin);
 scanf("%d",&n);
 for(i=0;i<n;i++)
 {
     scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
     set[++settop]=a[i][0];
     set[++settop]=a[i][1];
 }
 qsort(set,2*n,sizeof(set[0]),cmp);
 rset[++rsettop]=set[0];
 for(i=1;i<=settop;i++)
 {
  if(set[i]!=set[i-1])
  rset[++rsettop]=set[i];
 }
 build(0,rsettop);
 for(i=0;i<n;i++)
 {
     insert(a[i][0],a[i][1],a[i][2],0);
 }
 dfs(0);
 printf("%lld\n",sum);
 return 0;
}

这道题很强大,这样写很浪费时间,关键在于面积只需要最后才统计,所以插入过程中并不需要维护线段树,所以化简吧~~~

void insert(int p,int q,int c,int k)
{
 if(rset[tree[k].a]>=p && rset[tree[k].b]<=q)
 {  
     tree[k].high=tree[k].high>c?tree[k].high:c;
     return ;
 }
 if(p<rset[tree[k].mid]) insert(p,q,c,tree[k].ld);
 if(q>rset[tree[k].mid]) insert(p,q,c,tree[k].rd);
}
  
void dfs(int k)
{
 if(tree[k].b-tree[k].a==1)
 {
     sum+=(rset[tree[k].b]-rset[tree[k].a])*(long long)tree[k].high;
     return ;
 }
 tree[tree[k].ld].high=tree[k].high>tree[tree[k].ld].high?tree[k].high:tree[tree[k].ld].high;
 tree[tree[k].rd].high=tree[k].high>tree[tree[k].rd].high?tree[k].high:tree[tree[k].rd].high; 
 dfs(tree[k].ld);
 dfs(tree[k].rd);
}

速度达到180ms了~~~

posted on 2011-02-25 21:18  雨^痕  阅读(147)  评论(0)    收藏  举报