P3875 [TJOI2010]被污染的河流

链接:Miku

-------------------------

我记得扫描线有一道更水的例题来

-------------------------

扫描线,顾名思义,我们做这道题的时候,就要是用一道线来扫描一样

这里有一堆矩阵,把每一个区间拆成上下两个线段,然后按照某一个端点排序,这道线就开始从头扫描

到了一个矩阵开始的线,我们就更新扫描线的长度,反之减少即可

两个线段之间的长度很明显就是区间距离*扫描线长度即可

-----------------------------

直接这么写只有30分,还是要用线段树维护的

线段树可以加快我们查询扫描线长度和更新扫描线长度的速度

------------------------------

 这里的线段树我lazy记录的区间被修改次数,然后sum是区间长度(为1的数量),显然,根节点就是我们需要的,而且没必要写查询函数

但是我的做法继续操作的相对行,有减必然有长度一样的加,所以我的代码中不需要pushdown(加了还错,至少我是)

而且考虑到lazy和sum的区别,pushup会调用的更加频繁,甚至会pushup(叶子节点),然而叶子节点没有左右节点,要特判(也可能是我线段树写法的问题)

-------------------------------

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int x1,y1,x2,y2;
long long ans;
struct li{
    int l;
    int r;
    long long  h;
    int f;
}line[200005];
int n;
int p;
int sum[4000005];
int lazy[4000005];
bool cmp(li x,li y){
    return x.h<y.h;
}
void pushup(int x,int l,int r){
    if(lazy[x]>=1)//如果被改了,肯定就是区间的长度了 
        sum[x]=r-l+1;
    else if(l!=r)
        sum[x]=sum[x<<1]+sum[x<<1|1];//考虑叶子节点 的问题 
    else
        sum[x]=0;
}
void update(int x,int l,int r,int L,int R,int d){
    if(L<=l&&r<=R){
        lazy[x]+=d;
        pushup(x,l,r);//冗长的特判不如加到一起 
        return ;
    }
    int mid=(l+r)>>1;
    if(L<=mid) update(x<<1,l,mid,L,R,d);
    if(R>mid) update(x<<1|1,mid+1,r,L,R,d);
    pushup(x,l,r);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);//非常奇特的输入 
        if(x1>x2)
            swap(x1,x2);
        if(y1>y2)
            swap(y1,y2);
            //f的值是1或-1可以省事 
        if(x1==x2){
            p++;//自己造矩形 
            line[p].l=y1+1;
            line[p].r=y2;
            line[p].h=x1-1;
            line[p].f=1;
            p++;
            line[p].l=y1+1;
            line[p].r=y2;
            line[p].h=x1+1;
            line[p].f=-1;
        }
        else{
            p++;
            line[p].l=y1;
            line[p].r=y1+1;
            line[p].h=x1;
            line[p].f=1;
            p++;
            line[p].l=y1;
            line[p].r=y1+1;
            line[p].h=x2;
            line[p].f=-1;
        }
    }
    sort(line+1,line+p+1,cmp);
    for(int i=1;i<=p;++i){
        ans+=(line[i].h-line[i-1].h)*sum[1];//显然 
        update(1,0,1000005,line[i].l,line[i].r,line[i].f);//就在这省事 
    }
    cout<<ans;
    return 0;
}
Ac

猜你喜欢

转载自www.cnblogs.com/For-Miku/p/12384624.html