• POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)


    题目原网址:http://poj.org/problem?id=1177

    题目中文翻译:

    解题思路:

    总体思路:

    1.沿X轴离散化建树

    2.按Y值从小到大排序平行与X轴的边,然后顺序处理

        如果遇到矩形下面那条边则插入到线段树中,遇到矩形上面的边则将相应的边删除掉

        根据线段树当前的状态统计长度

     

    第二点是本题的核心思想,偶再举个例:

    POJ1177 <wbr>Picture(线段树求轮廓周长)
      第一次求出的部分很好理解.

      第二次求出的为什么会少了中间那部分.那是因为插入的新线段覆盖了第一条,此时线段树返回的长度是新的那一条的长度,将这个值再减去上次的就少了中间那部分

      第三次因为是矩形的上边,所以要删除在那条长的线段.此时的线段树返回的则是第一次的长度,将此值减去第二次返回值,再取其负值就是红色X轴那部分了

      最后那条X轴的,再补上就行了.

     

     需要注意的就是离散化以后一定要去掉重复元素,否则会出错的。

    转载自:传送门

    AC代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 
      5 using namespace std;
      6 
      7 struct kkk {
      8     int l,r;//线段树表示区间范围 
      9     int cnt;//有效长度 
     10     int lf,rf;//实际左右端点 
     11     int numseg;//分支数,一个分支对应两条竖线 
     12     int c;//记录覆盖情况 
     13     bool lc,rc;//左右半覆盖情况 
     14 }s[40040];
     15 
     16 struct ll {
     17     int y;
     18     int x1,x2;
     19     int f;//表示出入边,入边为1,出边为-1(自己想想为什么) 
     20 }l[10010];
     21 
     22 int x[10010];
     23 
     24 bool cmp(ll a,ll b) {
     25     return a.y < b.y;
     26 }
     27 
     28 void build(int i,int le,int r) {//建树 
     29     s[i].l = le;
     30     s[i].r = r;
     31     s[i].lf = x[le];
     32     s[i].rf = x[r];
     33     s[i].cnt = 0;
     34     s[i].numseg = 0;
     35     s[i].c = 0;
     36     s[i].lc = s[i].rc = false;
     37     if(le + 1 == r) return ;
     38     int mid = (le + r) / 2;
     39     build(i << 1,le,mid);
     40     build((i << 1) | 1,mid,r);
     41 }
     42 
     43 void calen(int i) {//计算长度 
     44     if(s[i].c > 0) {
     45         s[i].cnt = s[i].rf - s[i].lf;
     46         s[i].numseg = 1;
     47         s[i].lc = s[i].rc = true;
     48         return ;
     49     }
     50     if(s[i].l + 1 == s[i].r) {
     51         s[i].cnt = 0;
     52         s[i].numseg = 0;
     53         s[i].lc = s[i].rc = false;
     54     }
     55     else {
     56         s[i].cnt = s[i<<1].cnt + s[(i<<1)|1].cnt;
     57         s[i].lc = s[i<<1].lc;
     58         s[i].rc = s[(i<<1)|1].rc;
     59         s[i].numseg = s[i<<1].numseg + s[(i<<1)|1].numseg;
     60         if(s[i<<1].rc&&s[(i<<1)|1].lc) s[i].numseg--;
     61     }
     62 }
     63 
     64 void update(int i,ll e) {
     65     if(s[i].lf == e.x1 && s[i].rf == e.x2) {
     66         s[i].c += e.f;
     67         calen(i);
     68         return ;
     69     }
     70     if(e.x2 <= s[i<<1].rf) update(i << 1,e);
     71     else if(e.x1 >= s[(i<<1)|1].lf) update((i<<1) | 1,e);
     72     else {
     73         ll temp = e;
     74         temp.x2 = s[i<<1].rf;
     75         update(i << 1,temp);
     76         temp = e;
     77         temp.x1 = s[i<<1|1].lf;
     78         update((i<<1)|1,temp);
     79     }
     80     calen(i);
     81 }
     82 
     83 int main()
     84 {
     85     int x1,y1,x2,y2;
     86     int n;
     87     while(scanf("%d",&n) == 1) {
     88         int t = 0;
     89         for(int i = 0;i < n; i++) {
     90             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
     91             l[t].x1 = x1;
     92             l[t].x2 = x2;
     93             l[t].y = y1;
     94             l[t].f = 1;
     95             x[t++] = x1;
     96             l[t].x1 = x1;
     97             l[t].x2 = x2;
     98             l[t].y = y2;
     99             l[t].f = -1;
    100             x[t++] = x2;
    101         }
    102         sort(l,l+t,cmp);
    103         sort(x,x+t);
    104         int m = unique(x,x+t) - x;
    105         build(1,0,m-1);
    106         int ans = 0;
    107         int last = 0;
    108         for(int i = 0;i < t - 1; i++) {
    109             update(1,l[i]);
    110             ans += s[1].numseg * 2 * (l[i+1].y - l[i].y);
    111             ans += abs(s[1].cnt - last);
    112             last = s[1].cnt;
    113         }
    114         update(1,l[t-1]);
    115         ans += abs(s[1].cnt - last);
    116         printf("%d
    ",ans);
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    bigtint;int;smallint;tinyint
    修改sqlserver2008默认的数据库文件保存路径
    通过代码来调用log4net写日志
    supersocket中的日志处理
    QuickStart下的CommandFilter项目 github上自己修改过的版本
    演练:实现支持基于事件的异步模式的组件
    BroadcastService的测试用例
    2-Medium下的MultipleCommandAssembly
    如何获取supersocket的源代码
    supersocket中quickstart文件夹下的MultipleCommandAssembly的配置文件分析
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/10933737.html
Copyright © 2020-2023  润新知