poj 1177 线段树+离散化+扫描线 求矩形并的轮廓长

来源:互联网 发布:facebook关闭人工智能 编辑:程序博客网 时间:2024/05/16 09:09

Picture


题意:求矩形面积并额轮廓长

解法:扫描线+离散化+线段树


  • 做法:等于更新操作前后的tree[1].len差,做法这么巧妙实际我也不知道为什么。差不多的意思就是更新操作的cover变化长度就是新添加的段或者是删除掉的段,再加上最开始和最后的段更新。


  • 两次根据离散去建立线段树进行统计,得到sum=平行y轴的长度+平行于x轴的长度


  • 方法真的很巧妙,线段树博大精深 

[代码]

  1. #include<iostream> 
  2. #include<cstring> 
  3. #include <algorithm> 
  4. #include<cstdlib> 
  5. #include<vector> 
  6. #include<cmath> 
  7. #include<stdlib.h> 
  8. #include<iomanip> 
  9. #include<list> 
  10. #include<deque> 
  11. #include<map> 
  12. #include <stdio.h> 
  13. #include <queue> 
  14.  
  15. #define maxn 50000+5 
  16.  
  17. #define inf 0x3f3f3f3f 
  18.   #define INF 0x3FFFFFFFFFFFFFFFLL 
  19. #define rep(i,n) for(i=0;i<n;i++) 
  20.  #define reP(i,n) for(i=1;i<=n;i++) 
  21.  
  22. #define ull unsigned long long 
  23.  #define ll long long 
  24. #define LL(x) x<<1 
  25.   #define RR(x) x<<1|1 
  26.  
  27. #define cle(a) memset(a,0,sizeof(a)) 
  28.  
  29. using namespace std; 
  30. int n; 
  31. struct Line{//扫描线 
  32.     int ly,ry; 
  33.     int x,y; 
  34.     int flag;//出入操作标志 
  35. }line[maxn]; 
  36. struct indata{//操作两次,所以先将数存入 
  37.     //存入读入数据 
  38.     int ip,x1,y1,x2,y2; 
  39.     indata(int a,int b,int c,int d){ 
  40.         x1=a,y1=b,x2=c,y2=d; 
  41.     } 
  42.     indata(){ 
  43.  
  44.     } 
  45. }dat[maxn]; 
  46. int hash[maxn]; 
  47. struct node{//线段树 
  48.     int l,r,flag; 
  49.     int lv,rv,len; 
  50.     int mid(){ 
  51.         return (l+r)>>1
  52.     } 
  53. }tree[maxn*4]; 
  54. void build(int rt,int l,int r) 
  55. {//赋值操作 
  56.     tree[rt].l=l,tree[rt].r=r; 
  57.     tree[rt].lv=hash[l],tree[rt].rv=hash[r]; 
  58.     tree[rt].flag=0,tree[rt].len=0
  59.     if(l+1==r)return;//叶子判断 
  60.     int mid=tree[rt].mid(); 
  61.     build(LL(rt),l,mid),build(RR(rt),mid,r); 
  62. void doit(int x)//更新cover 
  63.     if(tree[x].flag)tree[x].len=tree[x].rv-tree[x].lv;//被覆盖他的段最长 
  64.     else if(tree[x].l+1==tree[x].r)tree[x].len=0;//没有被覆盖并且是叶子 
  65.     else tree[x].len=tree[LL(x)].len+tree[RR(x)].len;//两个孩子的长度 
  66.     return
  67. void update(int rt,Line a){//更新操作 
  68.     if(a.ly==tree[rt].lv&&a.ry==tree[rt].rv){ 
  69.         tree[rt].flag+=a.flag; 
  70.         doit(rt);return
  71.     } 
  72.     if(a.ry<=tree[LL(rt)].rv)update(LL(rt),a); 
  73.     else if(a.ly>=tree[RR(rt)].lv)update(RR(rt),a); 
  74.     else
  75.         Line temp=a;temp.ry=tree[LL(rt)].rv;update(LL(rt),temp); 
  76.         temp=a;temp.ly=tree[RR(rt)].lv;update(RR(rt),temp); 
  77.     } 
  78.     doit(rt); 
  79. void input() 
  80.     int i;for(i=1;i<=n;i++){ 
  81.         int x1,y1,x2,y2; 
  82.         scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 
  83.         dat[i]=indata(x1,y1,x2,y2); 
  84.     } 
  85. bool cmpy(Line a,Line b) 
  86.     return a.x<b.x; 
  87. void output(Line a) 
  88.     cout<<a.ly<<':'<<a.ry<<":"<<a.flag<<endl; 
  89. int main() 
  90. #ifndef ONLINE_JUDGE 
  91.      freopen("in.txt","r",stdin); 
  92.      //freopen("out.txt","w",stdout); 
  93. #endif 
  94.     while(scanf("%d",&n)!=EOF){ 
  95.         input(); 
  96.         //先对平行y轴进行操作 
  97.         int i; 
  98.         for(i=1;i<=n;i++){ 
  99.             line[2*i-1].ly=dat[i].y1,line[2*i-1].ry=dat[i].y2; 
  100.             line[2*i-1].x=dat[i].x1,line[2*i-1].flag=1
  101.             line[2*i].ly=dat[i].y1,line[2*i].ry=dat[i].y2; 
  102.             line[2*i].x=dat[i].x2,line[2*i].flag=-1
  103.             hash[2*i-1]=dat[i].y1,hash[2*i]=dat[i].y2; 
  104.         } 
  105.         int m=2*n; 
  106.         sort(line+1,line+1+m,cmpy),sort(hash+1,hash+m+1); 
  107.         build(1,1,m);update(1,line[1]); 
  108.         ll ans=0
  109.         int temp,tt; 
  110.         temp=tree[1].len;ans+=temp; 
  111.         for(i=2;i<=m;i++) 
  112.         { 
  113.             temp=tree[1].len; 
  114.         //    output(line[i]); 
  115.             update(1,line[i]); 
  116.             tt=tree[1].len; 
  117.             ans+=abs(temp-tt); 
  118.         } 
  119.         for(i=1;i<=n;i++){ 
  120.             line[2*i-1].ly=dat[i].x1,line[2*i-1].ry=dat[i].x2; 
  121.             line[2*i-1].x=dat[i].y1,line[2*i-1].flag=1
  122.             line[2*i].ly=dat[i].x1,line[2*i].ry=dat[i].x2; 
  123.             line[2*i].x=dat[i].y2,line[2*i].flag=-1
  124.             hash[2*i-1]=dat[i].x1,hash[2*i]=dat[i].x2; 
  125.         } 
  126.         sort(line+1,line+1+m,cmpy),sort(hash+1,hash+m+1); 
  127.         build(1,1,m);update(1,line[1]); 
  128.         temp=tree[1].len;ans+=temp; 
  129.         for(i=2;i<=m;i++){ 
  130.             temp=tree[1].len; 
  131.             update(1,line[i]);tt=tree[1].len; 
  132.             ans+=abs(temp-tt); 
  133.         } 
  134.         printf("%I64d\n",ans); 
  135.     } 
  136.     return 0
  137. }
0 0
原创粉丝点击