Picture hdu-1828 扫描线求面积+一组hack数据 为什么会wa?有可能是因为这个!两种方法!

题意:求矩形并周长
这里给出一组hack数据

47
-1155 -1105 -285 -930
-1115 -765 -375 -615
-480 -705 -285 -165
-1200 -705 -1025 -175
-1105 -275 -385 -105
-1165 -10 -285 185
-1160 315 -710 400
-1195 340 -1070 655
-1140 580 -265 655
-480 325 -335 395
-390 365 -265 620
-770 365 -665 610
-1195 815 -1070 1110
-760 825 -660 1100
-405 810 -275 1115
-700 780 -360 860
-695 1065 -360 1130
-1110 775 -735 860
-1110 1070 -730 1145
-95 -1065 260 140
80 -725 460 750
-135 135 840 490
-135 135 750 490
40 -520 945 -210
620 -595 695 215
-5 670 610 855
-75 550 -25 830
240 815 370 1085
-90 980 145 1125
150 280 315 490
-155 -1035 -90 -845
815 855 1030 950
980 785 1165 860
985 945 1160 1015
835 730 895 1075
695 875 790 935
420 -1165 650 -520
815 -1090 945 -210
800 -130 1160 65
980 120 1150 690
995 -1140 1180 -125
1050 -825 1135 -195
865 -90 1090 10
1045 280 1090 625
1065 -655 1115 -245
70 -1155 315 -790
110 -1005 225 -825

这道题呢,有两种方法可以做。一种是两根扫描线,一种是对于每个查询的X轴上的长度,可以通过作与上一个状态的差值的绝对值来得到的,那么要乘以多少次Y轴的长度,就只会受到连续区间段的影响。

我一开始想的是用两根扫描线去做。但是一直会wa,不知道为什么。自己实在想不出来,去问了学长和龙佬,最后发现bug。

我们扫描线时,需要将边从升序排序。如果两个边高度相同呢?这时候边的顺序就有可能会导致bug。

在这里插入图片描述

如图,我们有4条边,按照之前想的办法,我们进行处理,我们先放进去1这号边,再放入2这号边,实际上,这时候我们已经把下面的那个矩形块的周长完全计算了一遍,这时候其实我们已经算了2号的这条边,但是呢,我们再放进去3这号边的时候,其实又要去把3这号边的值给计算一遍,而且完完全全的是加3这号的边,那么实际上就把2这条边连续加了两次,而实际上呢,它并未产生贡献。

虽然,不经过这样的考虑也是可以AC的,弱数据(可能是随机数造的吧开森),但是今天突然被问到这个,于是想到了,扫描线确实还有一些小细节尤为重要,现在写下来,自省。

处理的方式呢?我们不妨在同等的高度上,我们先放进去要增入的边,在减去其余的边,我们就可以让那些由于先减后删多出来的贡献给消除掉了。所以,在对于y的排序上,我们先考虑y是否相同,若是相同了,我们先放入“val == 1”的加的部分,然后再是“val == -1”的减的部分。
(转自https://blog.csdn.net/qq_41730082/article/details/104036421

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
//#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int maxn=5E3+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
struct node{
    LL sum;
    int cnt;
}tree[maxn<<3];
struct node0{
    int x1,y1,x2,y2;
}s[maxn<<2];
struct node1{
    int x1,x2,y;
    int kind;
}edge[maxn<<2];
bool cmp(node1 a,node1 b){ return a.y==b.y?a.kind>b.kind:a.y<b.y;}

int lsh[maxn<<2];//k=1h k=0s

void push_up(int l,int r,int root){
    if (tree[root].cnt) tree[root].sum=lsh[r+1]-lsh[l];
    else if (l==r) tree[root].sum=0;
    else tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
}

void update(int l,int r,int ql,int qr,int root,int cnt){
    if (l==ql&&r==qr){
        tree[root].cnt+=cnt;
        push_up(l,r,root);
        return;
    }
    int mid=(l+r)>>1;
    if (qr<=mid) update(l,mid,ql,qr,root<<1,cnt);
    else if (ql>mid) update(mid+1,r,ql,qr,root<<1|1,cnt);
    else{
        update(l,mid,ql,mid,root<<1,cnt);
        update(mid+1,r,mid+1,qr,root<<1|1,cnt);
    }
    push_up(l,r,root);
}

int main (){
    int n;
    while (~scanf("%d",&n)){
        int cnt=0;
        for (int i=1;i<=n;i++){
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            s[i].x1=x1,s[i].y1=y1,s[i].x2=x2,s[i].y2=y2;
            edge[++cnt].x1=x1,edge[cnt].x2=x2,edge[cnt].y=y1,edge[cnt].kind=1,lsh[cnt]=x1;
            edge[++cnt].x1=x1,edge[cnt].x2=x2,edge[cnt].y=y2,edge[cnt].kind=-1,lsh[cnt]=x2;
        }
        sort(edge+1,edge+1+cnt,cmp);
        sort(lsh+1,lsh+1+cnt);
        int len=unique(lsh+1,lsh+1+cnt)-lsh;
        LL ans=0;
        LL last=0;
        for (int i=1;i<=cnt;i++){
            int l=lower_bound(lsh+1,lsh+len,edge[i].x1)-lsh;
            int r=lower_bound(lsh+1,lsh+len,edge[i].x2)-lsh-1;
            update(1,len,l,r,1,edge[i].kind);
            ans+=abs(tree[1].sum-last);
            last=tree[1].sum;
        }
        cnt=0;
        for (int i=1;i<=n;i++){
            int x1=s[i].y1,x2=s[i].y2,y1=s[i].x1,y2=s[i].x2;
            edge[++cnt].x1=x1,edge[cnt].x2=x2,edge[cnt].y=y1,edge[cnt].kind=1,lsh[cnt]=x1;
            edge[++cnt].x1=x1,edge[cnt].x2=x2,edge[cnt].y=y2,edge[cnt].kind=-1,lsh[cnt]=x2;
        }
        sort(edge+1,edge+1+cnt,cmp);
        sort(lsh+1,lsh+1+cnt);
        len=unique(lsh+1,lsh+1+cnt)-lsh;
        last=0;
        for (int i=1;i<=cnt;i++){
            int l=lower_bound(lsh+1,lsh+len,edge[i].x1)-lsh;
            int r=lower_bound(lsh+1,lsh+len,edge[i].x2)-lsh-1;
            update(1,len,l,r,1,edge[i].kind);
            ans+=abs(tree[1].sum-last);
            last=tree[1].sum;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
发布了41 篇原创文章 · 获赞 20 · 访问量 3016

猜你喜欢

转载自blog.csdn.net/weixin_43925900/article/details/104036748