poj1436

  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 */

 

你可能感兴趣的:(poj)