挺不错的一道线段树,薛神给的礼物,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 }