为什么加边的那条边是-1会有影响
思路:线段树维护一个twice表示有两条及以上线段覆盖的长度,once表示有一条覆盖的长度
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=2010;
int n;
double x[maxn];
struct seg
{
double l,r,h;
int c;
seg(){}
seg(double a,double b,double d,int t):l(a),r(b),h(d),c(t){}
bool operator<(const seg &a)const
{
if(h==a.h)return c>a.c;
return h<a.h;
}
}s[maxn];
struct IntervalTree
{
double once[maxn<<3],twice[maxn<<3];
int cnt[maxn<<3];
void build()
{
memset(cnt,0,sizeof(cnt));
memset(once,0,sizeof(once));
memset(twice,0,sizeof(twice));
}
void maintain(int o,int l,int r)
{
if(cnt[o]>=2)
{
twice[o]=x[r+1]-x[l];
once[o]=0;
}
else if(cnt[o]==1)
{
twice[o]=once[o<<1]+once[o<<1|1]+twice[o<<1]+twice[o<<1|1];
once[o]=x[r+1]-x[l]-twice[o];
}
else
{
twice[o]=twice[o<<1]+twice[o<<1|1];
once[o]=once[o<<1]+once[o<<1|1];
}
}
void update(int o,int l,int r,int q1,int q2,int t)
{
if(q1<=l&&r<=q2)
{
cnt[o]+=t;
maintain(o,l,r);
return ;
}
int mid=(l+r)>>1;
if(q1<=mid)update(o<<1,l,mid,q1,q2,t);
if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,t);
maintain(o,l,r);
}
}tree;
int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int num=1;
double a,b,c,d;
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
x[num]=a;
s[num++]=seg(a,c,d,-1);
x[num]=c;
s[num++]=seg(a,c,b,1);
}
sort(x+1,x+num);
sort(s+1,s+num);
int nx=unique(x+1,x+num)-x-1;
double ans=0;
tree.build();
for(int i=1;i<num-1;i++)
{
int l=lower_bound(x+1,x+nx+1,s[i].l)-x;
int r=lower_bound(x+1,x+nx+1,s[i].r)-x-1;
tree.update(1,1,nx,l,r,s[i].c);
ans+=tree.twice[1]*(s[i+1].h-s[i].h);
}
printf("%.2f\n",ans);
}
return 0;
}