题意:给定一个二维平面,再给你n条垂直线条,如果有两条线段能用水平的线连接且不水平的线不接触其他线段,则说明这条两条线段可见,如果三条线段两两可见,则代表一个“三角形”,问给定线段集合中的“三角形”个数,
解题思路:线段树区间覆盖加统计,要把区间变为点数,所以所有点的 y 都要 乘 2 。 不会stl的童鞋伤不起,用链表统计,更新,最后在暴力找个数。
解题代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #define maxn 8005 5 int hs[maxn]; 6 struct op 7 { 8 int y1,y2,x; 9 } ops[maxn]; 10 int cmp(const void *a , const void *b) 11 { 12 return (*(op*)a).x - (*(op*)b).x; 13 } 14 struct li 15 { 16 int num ; 17 struct li*next; 18 }ths[maxn]; 19 struct li * newli() 20 { 21 struct li *p = (li*)malloc(sizeof(li)); 22 p->num = 0 ; 23 p->next = NULL; 24 return p ; 25 } 26 struct node 27 { 28 int l , r, m ; 29 int c ; 30 struct li head; 31 struct li* last; 32 } tree[maxn*8]; 33 int L(int c) 34 { 35 return 2*c; 36 } 37 int R(int c) 38 { 39 return 2*c + 1; 40 } 41 void Free(struct li *p) 42 { 43 if(p->next != NULL) 44 Free(p->next); 45 free(p); 46 } 47 void build(int c, int p , int v) 48 { 49 tree[c].l = p ; 50 tree[c].r = v; 51 tree[c].m = (p + v)/2; 52 tree[c].c = 0 ; 53 tree[c].head.next = NULL; 54 tree[c].head.num = 0 ; 55 tree[c].last = &tree[c].head; 56 if(p == v) 57 return ; 58 build(L(c),p,tree[c].m); 59 build(R(c),tree[c].m+1,v); 60 } 61 62 void Pushdown(int c) 63 { 64 65 if(tree[c].c != 0) 66 { 67 tree[L(c)].c = tree[c].c; 68 tree[R(c)].c = tree[c].c; 69 struct li *p; 70 p = newli(); 71 p->num = tree[c].c; 72 tree[L(c)].head.num = 1; 73 tree[L(c)].head.next = p ; 74 tree[L(c)].last = p; 75 p = newli(); 76 p->num = tree[c].c; 77 tree[R(c)].head.num = 1; 78 tree[R(c)].head.next = p ; 79 tree[R(c)].last = p; 80 tree[c].c = 0; 81 } 82 } 83 84 void Pushup(int c) 85 { 86 tree[c].head.num = tree[L(c)].head.num + tree[R(c)].head.num; 87 tree[L(c)].last->next = tree[R(c)].head.next; 88 tree[c].head.next = tree[L(c)].head.next; 89 if(tree[c].head.num == 0 ) 90 tree[c].last = &tree[c].head; 91 else if(tree[R(c)].head.num == 0) 92 tree[c].last = tree[L(c)].last; 93 else tree[c].last = tree[R(c)].last; 94 } 95 void update(int c, int p , int v, int value) 96 { 97 if(p <= tree[c].l &&v >= tree[c].r) 98 { 99 tree[c].c = value; 100 struct li *p = &tree[c].head; 101 for(int i = 1; i <= tree[c].head.num; i ++) 102 { 103 p = p->next ; 104 hs[p->num] = 1; 105 } 106 p = newli(); 107 p->num = value; 108 tree[c].head.num = 1; 109 tree[c].head.next = p ; 110 tree[c].last = p; 111 return ; 112 } 113 Pushdown(c); 114 if(v <= tree[c].m) update(L(c),p,v,value); 115 else if(p > tree[c].m) update(R(c),p,v,value); 116 else 117 { 118 update(L(c),p,tree[c].m,value); 119 update(R(c),tree[c].m+1,v,value); 120 } 121 Pushup(c); 122 } 123 int sum =0 ,n; 124 void fuck(int k) 125 { 126 for(int i = n;i >= 1;i --) 127 { 128 if(hs[i] == 1) 129 { 130 ths[k].num++; 131 struct li *p = newli(); 132 p->num = i ; 133 p->next = ths[k].next ; 134 ths[k].next = p ; 135 } 136 } 137 } 138 void F(int k) 139 { 140 struct li * p1 ,*p2 ; 141 p1 = &ths[k]; 142 bool visit[maxn] = {0}; 143 for(int i = 1; i <= ths[k].num ; i++) 144 { 145 p1 = p1->next; 146 visit[p1->num] = 1; 147 p2 = &ths[p1->num]; 148 for(int j= 1; j <= ths[p1->num].num; j ++) 149 { 150 p2 = p2->next; 151 if(visit[p2->num]) 152 sum ++; 153 } 154 } 155 } 156 int main() 157 { 158 int t ; 159 scanf("%d",&t); 160 while(t--) 161 { 162 sum = 0 ; 163 memset(tree,0,sizeof(tree)); 164 memset(ths,0,sizeof(ths)); 165 scanf("%d",&n); 166 for(int i =1 ; i <= n; i ++) 167 scanf("%d %d %d",&ops[i].y1,&ops[i].y2,&ops[i].x); 168 qsort(ops +1 , n, sizeof(op),cmp); 169 build(1,0,2*maxn); 170 for(int i= 1; i <= n; i ++) 171 { 172 memset(hs,0,sizeof(hs)); 173 update(1,ops[i].y1*2,ops[i].y2*2,i); 174 fuck(i); 175 F(i); 176 } 177 printf("%d\n",sum); 178 } 179 return 0; 180 }