虽然是过,其实我也没想会过,这样做竟不超时,有点厉害
不过也有点慢了,回来再做过
我用了lazy思想,由于每次都要tree_search使得其很慢,网上有些代码是
增加记录域ylenonce,ylenmore分别是记录覆盖一次的长度,覆盖二次以上的长度
这样就不要tree_searh了,快了不知多少~~~
我的代码:
using namespace std;
struct elem{
double x;
double ly;
double ry;
bool flag;
};
struct node{
int l;
int r;
double m;
int cover;
bool flag1;
};
elem cor[2*N];
node tree[8*N];
double index[2*N];
int len;
int n;
double res;
int cmp(const void *a,const void *b)
{
if((*(elem*)a).x > (*(elem *)b).x)
return 1;
else if((*(elem*)a).x == (*(elem *)b).x)
return 0;
else
return -1;
}
int cmp1(const void *a,const void *b)
{
if(*(double *)a > *(double *)b)
return 1;
else if(*(double *)a == *(double *)b)
return 0;
else
return -1;
}
void init()
{
int i;
int k;
double x1,y1,x2,y2;
scanf("%d",&n);
for(i = 0;i < n;i++){
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
k = i<<1;
cor[k].x = x1; cor[k].ly = y1; cor[k].ry = y2;
cor[k].flag = true;
cor[k+1].x = x2; cor[k+1].ly = y1; cor[k+1].ry = y2;
cor[k+1].flag = false;
index[k] = y1; index[k+1] = y2;
}
qsort(cor,2*n,sizeof(cor[0]),cmp);
qsort(index,2*n,sizeof(index[0]),cmp1);
len = 0;
for(i = 1;i < 2*n;i++){
if(index[i] != index[i-1])
index[++len] = index[i];
}
return ;
}
int find(double x)
{
int mid;
int base = 0,top = len;
while(base <= top){
mid = (base+top)/2;
if(x < index[mid])
top = mid-1;
else if(x > index[mid])
base = mid+1;
else return mid;
}
return -1;
}
void buid_tree(int k,int left,int right)
{
int mid;
int L,R;
tree[k].l = left; tree[k].r = right;//if(tree[k].l == 4 && tree[k].r == 5) cout <<"k:" <<k <<endl;
tree[k].m = 0; tree[k].cover = 0; tree[k].flag1 = false;
if(tree[k].r-tree[k].l == 1)
return ;
mid = (tree[k].l+tree[k].r)/2;
L = k<<1; R = L+1;
buid_tree(L,left,mid);
buid_tree(R,mid,right);
return ;
}
void init_m(int k)
{
int L,R;
if(tree[k].cover >= 2){
tree[k].m = index[tree[k].r]-index[tree[k].l];
return ;
}
L = k<<1; R = L+1;
if(tree[k].r-tree[k].l > 1){
tree[k].m = tree[L].m+tree[R].m;
return ;
}
tree[k].m = 0;
return ;
}
void tree_insert(int k,int left,int right)
{
int mid;
int L,R;
if(left <= tree[k].l && right >= tree[k].r){
tree[k].cover++;//cout <<'(' <<tree[k].l <<',' <<tree[k].r <<',' <<tree[k].cover <<") ";
//init_m(k);
tree[k].flag1 = true;
return ;
}
mid = (tree[k].l+tree[k].r)/2;
L = k<<1; R = L+1;
if(tree[k].cover){
tree[L].cover += tree[k].cover;
tree[R].cover += tree[k].cover;
tree[k].cover = 0;
}
if(left < mid) tree_insert(L,left,right);
if(right > mid) tree_insert(R,left,right);
//init_m(k);
return ;
}
void tree_delete(int k,int left,int right)
{
int mid;
int L,R;//if(tree[k].l == 4 && tree[k].r == 5)cout <<"dgd:" <<tree[k].cover <<endl;
if(left <= tree[k].l && right >= tree[k].r){
tree[k].cover--;
tree[k].flag1 = true;
//init_m(k);
return ;
}
mid = (tree[k].l+tree[k].r)/2;
L = k<<1; R = L+1;
if(tree[k].cover){
tree[L].cover += tree[k].cover;
tree[R].cover += tree[k].cover;
tree[k].cover = 0;
}
if(left < mid) tree_delete(L,left,right);
if(right > mid) tree_delete(R,left,right);
//init_m(k);
return ;
}
void tree_search(int k)
{
int L,R;
if(tree[k].cover > 1){
//init_m(k);
tree[k].m = index[tree[k].r]-index[tree[k].l];//cout <<tree[k].r <<'-' <<tree[k].l << ' ';
return ;
}
if(tree[k].r-tree[k].l == 1){
tree[k].m = 0;
return ;
}
L = k<<1; R = L+1;
if(tree[k].cover){
tree[L].cover += tree[k].cover;
tree[R].cover += tree[k].cover;
tree[k].cover = 0;
}
tree_search(L);
tree_search(R);
//init_m(k);
tree[k].m = tree[L].m+tree[R].m;
return ;
}
int main()
{
int tcase;
int i;int l,r;
scanf("%d",&tcase);
while(tcase--){
init();
buid_tree(1,0,len);
res = 0;
for(i = 0;i < (2*n-1);i++){
l = find(cor[i].ly); r = find(cor[i].ry);
if(cor[i].flag){
tree_insert(1,l,r);
}
else
tree_delete(1,l,r);
tree_search(1);
res += tree[1].m*(cor[i+1].x-cor[i].x);
}
printf("%.2lf/n",res);
}
return 0;
}