• ZOJ 1391 Horizontally Visible Segments


    挺不错的一道线段树,薛神给的礼物,WA了整整一天才过,各种细节出错OTL……

    1.纵坐标扩大两倍保存,不然样例都跑不过。即(0, 2)与(3, 4)之间可以有一条横线,但是如果坐标不扩大,这条横线是过不去的。

    2.按x值从小到大排序,插入线段树,每次将Line[id]更新到线段树中之前,先查询编号为Line[id]向左可以看到哪几条线段(即可以看到哪几条编号比它小的线段),用vector保存,注意去重,不然最后结果会多。(vector忘了clear这里错了好几次。。。)

    3.id[MAXN]用来标记该段最顶端的线段的编号,-1代表该段没被覆盖或者该段不是被同一条线段覆盖

    4.四重循环暴力枚举,暂时也没想到别的好办法……或许是因为数据弱的缘故,交上去效率还可以,140ms AC。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <vector>
      5 #include <algorithm>
      6 
      7 #define lson l, m, rt << 1
      8 #define rson m + 1, r, rt << 1 | 1
      9 
     10 using namespace std;
     11 
     12 const int MAXLEN = 8010 << 1;
     13 const int MAXN = 8010;
     14 
     15 struct MyLine
     16 {
     17     int y1, y2;
     18     int x;
     19 };
     20 
     21 int N, bound;
     22 vector<int> see[MAXN];
     23 MyLine L[MAXN];
     24 
     25 int  id[ MAXLEN << 2 ];
     26 
     27 bool cmp( MyLine a, MyLine b )
     28 {
     29     return a.x < b.x;
     30 }
     31 
     32 void PushUp( int rt )
     33 {
     34     int lc = rt << 1;
     35     int rc = rt << 1 | 1;
     36     if ( id[lc] == id[rc] )
     37         id[rt] = id[lc];
     38     else
     39         id[rt] = -1;
     40     return;
     41 }
     42 
     43 void PushDown( int rt )
     44 {
     45     int lc = rt << 1;
     46     int rc = rt << 1 | 1;
     47     if ( id[rt] != -1 )
     48         id[lc] = id[rc] = id[rt];
     49 
     50     return;
     51 }
     52 
     53 bool check( int c, int tar )   //去除重点
     54 {
     55     int len = see[c].size();
     56     for ( int i = 0; i < len; ++i )
     57         if ( tar == see[c][i] ) return false;
     58     return true;
     59 }
     60 
     61 void Query( int L, int R, int c, int l, int r, int rt )
     62 {
     63     if ( id[rt] != -1 )
     64     {
     65         if ( check( c, id[rt] ) ) see[c].push_back( id[rt] );
     66         return;
     67     }
     68     if ( l >= r ) return;
     69     PushDown(rt);
     70     int m = ( l + r ) >> 1;
     71     if ( L <= m ) Query( L, R, c, lson );
     72     if ( R > m ) Query( L, R, c, rson );
     73 
     74     PushUp(rt);
     75     return;
     76 }
     77 
     78 void Update( int L, int R, int c, int l, int r, int rt )
     79 {
     80     if ( L <= l && r <= R )
     81     {
     82         id[rt] = c;
     83         return;
     84     }
     85     PushDown(rt);
     86     int m = ( l + r ) >> 1;
     87     if ( L <= m ) Update( L, R, c, lson );
     88     if ( R > m ) Update( L, R, c, rson );
     89     PushUp( rt );
     90     return;
     91 }
     92 
     93 int main()
     94 {
     95     int T;
     96     // freopen( "in.txt", "r", stdin );
     97     scanf( "%d", &T );
     98     while ( T-- )
     99     {
    100         scanf( "%d", &N );
    101         bound = 0;
    102 
    103         memset( id, -1, sizeof(id) );
    104         for ( int i = 0; i < N; ++i )
    105         {
    106             scanf("%d%d%d", &L[i].y1, &L[i].y2, &L[i].x );
    107             L[i].y1 *= 2;
    108             L[i].y2 *= 2;
    109             see[i].clear();  // 勿忘清空
    110             bound = max( bound, L[i].y2 );
    111         }
    112 
    113         sort( L, L + N, cmp );
    114 
    115         for ( int i = 0; i < N; ++i )
    116         {
    117             Query( L[i].y1, L[i].y2, i, 0, bound, 1 );
    118             Update( L[i].y1, L[i].y2, i, 0, bound, 1 );
    119         }
    120 
    121         int ans = 0;
    122         for ( int i = 0; i < N; ++i )
    123         {
    124             int sz = see[i].size();
    125             for ( int j = 0; j < sz; ++j )
    126             {
    127                 int i2 = see[i][j];    //i can see i2
    128                 int sz2 = see[i2].size();
    129                 for ( int y = 0; y < sz2; ++y )  //i2 can see see[i2][y]
    130                     for ( int x = 0; x < sz; ++x )
    131                     {
    132                         if ( x != j && see[i][x] == see[i2][y] )
    133                             ++ans;
    134                     }
    135             }
    136         }
    137 
    138         printf( "%d\n", ans );
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    linux系统下安全管理
    Linux查看所有用户用什么命令
    linux下配置ip地址四种方法(图文方法)
    如何在linux系统中设置静态ip地址
    算法与cpu
    汇编 分支之跳转结构程序设计--待处理文档
    从汇编的角度理解程序(二)—— 分支和循环控制
    指令计数器--Program counter
    类型的分类
    CPU的内部架构和工作原理
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3078268.html
Copyright © 2020-2023  润新知