题意:给你垂线段,求最多能找到多少三元组
解法:线段维护最新的阴影,并且建立关系
New point :所有的点乘以二进行维护
三元组的定义:任意两个垂线段可以相见,能够找到水平线连接两线段且不相交其他线段
对于插入的点都要乘以2,是因为对于[1,2],[3,4],对于线段[2,3]只能表示成分居两地的两个点,但是乘以二后,最小的线段长度=2,必然存在两个段
- /*************************************************************************
- > File Name: poj1436.cpp
- > Author: cy
- > Mail: 1002@qq.com
- > Created Time: 14/11/8 18:08:35
- ************************************************************************/
- #include<iostream>
- #include<cstring>
- #include <algorithm>
- #include<cstdlib>
- #include<vector>
- #include<cmath>
- #include<stdlib.h>
- #include<iomanip>
- #include<list>
- #include<deque>
- #include<map>
- #include <stdio.h>
- #include <queue>
- #define maxn 8000+100
- #define inf 0x3f3f3f3f
- #define INF 0x3FFFFFFFFFFFFFFFLL
- #define rep(i,n) for(i=0;i<n;i++)
- #define reP(i,n) for(i=1;i<=n;i++)
- #define ull unsigned long long
- #define ll long long
- #define cle(a) memset(a,0,sizeof(a))
- #define bug cout<<"____bug____"
- using namespace std;
- struct Edge{//可以连接的两个线段建边
- int to,next;
- }edge[maxn*1000];
- struct Tree{//线段树
- int l,r;
- int flag;//判断覆盖情况
- int mid(){
- return (l+r)/2;
- }
- }tree[80080];
- struct Date{
- int l,r,x;
- }date[maxn];
- bool cmp(Date a,Date b){
- return a.x<b.x;
- }
- int head[maxn];bool hash[maxn][maxn];int point[maxn];
- int num;
- void init(){
- memset(head,-1,sizeof(head));
- cle(hash);
- num=0;
- }
- void add(int a,int b){
- if(hash[a][b])return;
- edge[num].to=b,edge[num].next=head[a],head[a]=num++;
- hash[a][b]=hash[b][a]=true;
- }
- void build(int rt,int l,int r){//建立线段树
- tree[rt].l=l;
- tree[rt].r=r;
- tree[rt].flag=0;
- if(l==r)return;
- int mid=tree[rt].mid();
- build(rt*2,l,mid);
- build(rt*2+1,mid+1,r);
- }
- void update(int rt,int l,int r,int ip){
- if(tree[rt].l==l&&tree[rt].r==r&&tree[rt].flag!=-1){//可以进行更新操作
- add(tree[rt].flag,ip);
- tree[rt].flag=ip;
- return;
- }
- else{
- if(tree[rt].flag!=-1){
- tree[rt<<1].flag=tree[rt].flag;tree[rt<<1|1].flag=tree[rt].flag;//向下更新
- tree[rt].flag=-1;//表示遇到这一段必须向下更新(找阴影)
- }
- int mid=tree[rt].mid();
- if(r<=mid)update(rt<<1,l,r,ip);
- else if(l>mid)update(rt<<1|1,l,r,ip);
- else{
- update(rt<<1,l,mid,ip);update(rt<<1|1,mid+1,r,ip);
- }
- }
- }
- int main()
- {
- #ifndef ONLINE_JUDGE
- freopen("in.txt","r",stdin);
- //freopen("out.txt","w",stdout);
- #endif
- int n,T;cin>>T;
- while(T--)
- {
- scanf("%d",&n);
- init();
- int i,j,k;
- rep(i,n)scanf("%d%d%d",&date[i+1].l,&date[i+1].r,&date[i+1].x);
- sort(date+1,date+1+n,cmp);
- build(1,0,16000);
- rep(i,n){
- int l=date[i+1].l,r=date[i+1].r;
- update(1,l*2,r*2,i+1);
- }
- int tail=0;
- int ans=0;
- for(i=1;i<=n;i++){
- tail=0;
- for(j=head[i];j!=-1;j=edge[j].next){//这些线和i有阴影
- point[tail++]=edge[j].to;
- }
- rep(j,tail){//找另外的两个满足的线段
- for(k=j+1;k<tail;k++)
- {
- if(hash[point[j]][point[k]])ans++;
- }
- }
- }
- cout<<ans<<endl;
- }
- return 0;
- }