一、.思路:有三种方法
1.插入时延迟更新(我自己的做法),效率还不错,应该是最大最小值的剪枝的作用吧,呵呵!
2.插入时精确覆盖,查询时向下记录最大值,一直查询到叶子结点
3.扫描线+测度
在线段树的结点里增加n,m,n表示线段数量,m表示这个区间的有效长度,由于使用了扫描线,因此每次计算的是一个局部的范围,简化了问题,插入矩形的左边时,对应区间的线段树加1,插入右边时就减1,因为扫描线是向右的,碰到左边,开始作用,碰到右边取消其作用!和poj1177做法是一样的,效率也还可以!
注意插入时对测度的修改,当该区间没有线段时应该递归的求解!然后查询就是O(1)的时间了。
二、代码
思路1的代码
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define min(i,j) (i<j?i:j) #define max(i,j) (i>j?i:j) typedef __int64 LL; #define lson (root<<1) #define rson (root<<1|1) struct node { int st,ed,c; int maxi,mini; }ST[300000]; struct Line { int x1,x2,h; }line[40005]; int x[80005],tx[80005],n,num; void build(int root,int st,int ed) { ST[root].st=st; ST[root].ed=ed; ST[root].maxi=ST[root].mini=ST[root].c=0; if(ed>st+1) { build(lson,st,(st+ed)>>1); build(rson,(st+ed)>>1,ed); } } void insert(int root,int st,int ed,int c) { if(c<=ST[root].mini)return; int l=ST[root].st,r=ST[root].ed; if(st<=l&&r<=ed)//l==r-1|| { if(c>=ST[root].maxi) { ST[root].c=ST[root].maxi=ST[root].mini=c; return; } } if(ST[root].c>0) { ST[lson].c=ST[lson].maxi=ST[lson].mini=ST[root].c; ST[rson].c=ST[rson].maxi=ST[rson].mini=ST[root].c; ST[root].c=0; } int mid=(l+r)>>1; if(st<mid)insert(lson,st,ed,c); if(ed>mid)insert(rson,st,ed,c); ST[root].mini=min(ST[lson].mini,ST[rson].mini); ST[root].maxi=max(ST[lson].maxi,ST[rson].maxi); } int Correspond(int t) { int l=1,r=num; while(l<r) { int mid=(l+r)>>1; if(t>x[mid]) l=mid+1; else r=mid; } return r; } __int64 sum(int root) { int l=ST[root].st,r=ST[root].ed; if(ST[root].c>0)return (x[r]-x[l])*__int64(ST[root].c); if(l+1==r)return 0;// return sum(lson)+sum(rson); } int main() { #ifndef ONLINE_JUDGE // freopen("data.in", "r", stdin); freopen("horizon.10.in", "r", stdin); freopen("data.out","w",stdout); #endif int i; while(scanf("%d",&n)==1) { num=0; for(i=0;i<n;i++) { scanf("%d %d %d",&line[i].x1,&line[i].x2,&line[i].h); tx[num++]=line[i].x1,tx[num++]=line[i].x2; } sort(tx,tx+num); n<<=1; x[1]=tx[0]; for(i=num=1;i<n;i++) if(tx[i]!=tx[i-1]) x[++num]=tx[i]; build(1,1,num); n>>=1; for(i=0;i<n;i++) insert(1,Correspond(line[i].x1),Correspond(line[i].x2),line[i].h); printf("%I64d\n",sum(1)); } return 0; }
思路2的代码
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define min(i,j) (i<j?i:j) #define max(i,j) (i>j?i:j) typedef __int64 LL; #define lson (root<<1) #define rson (root<<1|1) #define N 40010 struct node { int st,ed,c; }ST[N*8]; struct Line { int x1,x2,h; }line[2*N]; int x[N*2],tx[N*2],n,num; void build(int root,int st,int ed) { ST[root].st=st; ST[root].ed=ed; ST[root].c=0; if(ed>st+1) { build(lson,st,(st+ed)>>1); build(rson,(st+ed)>>1,ed); } } void insert(int root,int st,int ed,int c) { int l=ST[root].st,r=ST[root].ed; if(st<=l&&r<=ed)//l==r-1|| { if(c>=ST[root].c)ST[root].c=c; return;//放在了if里面! } int mid=(l+r)>>1; if(st<mid)insert(lson,st,ed,c); if(ed>mid)insert(rson,st,ed,c); } int Correspond(int t) { int l=1,r=num; while(l<r) { int mid=(l+r)>>1; if(t>x[mid]) l=mid+1; else r=mid; } return r; } __int64 sum(int root,int maxi) { maxi=maxi<ST[root].c?ST[root].c:maxi; int l=ST[root].st,r=ST[root].ed; if(l+1==r)return __int64(maxi)*(x[r]-x[l]); return sum(lson,maxi)+sum(rson,maxi); } int main() { #ifndef ONLINE_JUDGE // freopen("data.in", "r", stdin); freopen("horizon.9.in", "r", stdin); #endif int i; while(scanf("%d",&n)==1) { num=0; for(i=0;i<n;i++) { scanf("%d %d %d",&line[i].x1,&line[i].x2,&line[i].h); tx[num++]=line[i].x1,tx[num++]=line[i].x2; } sort(tx,tx+num); n<<=1; x[1]=tx[0]; for(i=num=1;i<n;i++) if(tx[i]!=tx[i-1]) x[++num]=tx[i]; build(1,1,num); n>>=1; for(i=0;i<n;i++) insert(1,Correspond(line[i].x1),Correspond(line[i].x2),line[i].h); printf("%I64d\n",sum(1,0)); } return 0; }
思路3的代码
#include <iostream> #include<algorithm> #include<cstdio> #include<vector> #include<cstring> #include<string> using namespace std; #define lson (rt<<1) #define rson (lson|1) #define LL __int64 #define N 400010 struct Seg { int x,idx; bool left; }segs[2*N]; int cnt; bool cmp(const Seg & a,const Seg &b) { return a.x<b.x; } struct Node { int l,r,n; int m; void init(int ll,int rr) { l=ll,r=rr; n=m=0; } }tree[N*8]; int h[N],tot; int find(int height) { int l=0,r=tot-1,mid; while(l<r) { mid=(l+r)>>1; if(h[mid]<height)l=mid+1; else r=mid; } return l; } void build(int l,int r,int rt) { tree[rt].init(l,r); if(l<r-1) { int mid=(l+r)>>1; build(l,mid,lson); build(mid,r,rson); } } int getM(int rt) { if(tree[rt].m || tree[rt].l==tree[rt].r-1)return tree[rt].m; return tree[rt].m=getM(lson)+getM(rson); } void insert(int st,int ed,int rt,int num) { int l=tree[rt].l,r=tree[rt].r; if(st<=l&&ed>=r) { tree[rt].n+=num; if(tree[rt].n==1)tree[rt].m=h[r]-h[l]; else if(!tree[rt].n){tree[rt].m=0;getM(rt);}//叶子 return; } int mid=(l+r)>>1; if(st<mid)insert(st,ed,lson,num); if(ed>mid)insert(st,ed,rson,num); if(!tree[rt].n) { tree[rt].m=0; getM(rt); } } int main() { #ifndef ONLINE_JUDGE freopen("horizon.10.in", "r", stdin); #endif int n; while(~scanf("%d",&n)) { cnt=2*n; int i,l,r; for(i=0;i<n;i++) { l=i<<1,r=l|1; scanf("%d%d%d",&segs[l],&segs[r],h+i+1); segs[l].idx=segs[r].idx=h[i+1]; segs[l].left=true; segs[r].left=false; } h[0]=0; sort(h+1,h+n+1); for(tot=i=1;i<n+1;i++) { if(h[i]==h[tot-1])continue; h[tot++]=h[i]; } sort(segs,segs+cnt,cmp); for(i=0;i<cnt;i++)segs[i].idx=find(segs[i].idx); build(0,tot-1,1);// LL ans; for(ans=i=0;i<cnt;i++) { if(i)ans+=(segs[i].x-segs[i-1].x)*LL(tree[1].m); if(segs[i].left)insert(0,segs[i].idx,1,1); else insert(0,segs[i].idx,1,-1); } printf("%I64d\n",ans); } return 0; }