1 /* 2 题意:给你n条垂直线段,问有多少组三个线段,两两可见, 3 可见定义为对于两条线段有一条水平线段连接,不经过任意其他线段; 4 5 线段树建图,然后爆力判有几组(不知道效率如何); 6 从左到右扫描,先判断该区间内有可以连接哪几条线段,建图; 7 然后再插入; 8 9 问题:对于[1,4],[1,2],[3,4],[1,4] 10 如果直接1-2,3-4覆盖,当用1-4query的时候, 11 会发现不存在(2,3)区域的标记, 12 解决方法,每个点之间都插入一个点,用偶数表示原先的点, 13 用奇数表示点之间的区域,0,1,2,3,4 14 0 1 2 15 16 */ 17 #include<cstdio> 18 #include<cstring> 19 #include<cstdlib> 20 #include<algorithm> 21 #include<iostream> 22 #include<cmath> 23 #include<vector> 24 #define lson l,m,rt<<1 25 #define rson m+1,r,rt<<1|1 26 using namespace std; 27 const int N=8000+10; 28 struct Edge{ 29 int l,r,idx; 30 Edge(){} 31 Edge(int a,int b,int c):l(a),r(b),idx(c){} 32 void output(){ 33 cout<<l<<" "<<r<<" "<<idx<<endl; 34 } 35 }; 36 vector<Edge> g[N]; 37 vector<int> mz[N]; 38 bool vis[N][N]; 39 int n; 40 int col[N<<3];//要扩大 41 void pushdown(int rt){ 42 if (col[rt]!=-1){ 43 col[rt<<1]=col[rt<<1|1]=col[rt]; 44 col[rt]=-1; 45 } 46 } 47 void pushup(int rt){ 48 if (col[rt<<1]!=col[rt<<1|1]){ 49 col[rt]=-1; 50 }else col[rt]=col[rt<<1]; 51 } 52 void update(int L,int R,int v,int l,int r,int rt){ 53 if (L<=l && r<=R){ 54 col[rt]=v; 55 return; 56 } 57 pushdown(rt); 58 int m=(l+r)>>1; 59 if (L<=m) update(L,R,v,lson); 60 if (m< R) update(L,R,v,rson); 61 pushup(rt); 62 63 } 64 void query(int L,int R,int v,int l,int r,int rt){ 65 66 if (L<=l && r<=R && col[rt]!=-1){ 67 if (col[rt]==0) return ; 68 if (vis[v][col[rt]]==0){ 69 mz[v].push_back(col[rt]); 70 mz[col[rt]].push_back(v); 71 vis[v][col[rt]]=1; 72 vis[col[rt]][v]=1; 73 } 74 return ; 75 } 76 if (l==r) return; 77 pushdown(rt); 78 int m=(l+r)>>1; 79 if (L<=m) query(L,R,v,lson); 80 if (m< R) query(L,R,v,rson); 81 } 82 void work(){ 83 memset(col,0,sizeof(col)); 84 for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) vis[i][j]=0; 85 for (int i=0;i<N;i++){ 86 if (g[i].size()!=0){ 87 for (int j=0;j<g[i].size();j++){ 88 Edge u=g[i][j]; 89 query(u.l*2,u.r*2,u.idx,0,N*2-1,1); 90 } 91 for (int j=0;j<g[i].size();j++){ 92 Edge u=g[i][j]; 93 update(u.l*2,u.r*2,u.idx,0,N*2-1,1); 94 } 95 } 96 } 97 98 int ret=0; 99 for (int i=1;i<=n;i++){ 100 for (int j=0;j<mz[i].size();j++){ 101 int c=mz[i][j]; 102 for (int k=0;k<mz[c].size();k++){ 103 int w=mz[c][k]; 104 if (vis[w][i]) ret++; 105 } 106 } 107 } 108 printf("%d\n",ret/6); 109 } 110 void read(){ 111 int x,y1,y2; 112 for (int i=0;i<N;i++) { 113 g[i].clear();mz[i].clear(); 114 } 115 for (int i=0;i<n;i++){ 116 scanf("%d%d%d",&y1,&y2,&x); 117 g[x].push_back(Edge(y1,y2,i+1)); 118 } 119 } 120 int main(){ 121 int T;scanf("%d",&T); 122 while (T--){ 123 scanf("%d",&n); 124 read(); 125 work(); 126 } 127 128 } 129 /* 130 1 131 5 132 0 4 1 133 1 3 2 134 1 3 3 135 2 4 3 136 0 5 4 137 */