已AC,但有两处无法理解
查看原帖
已AC,但有两处无法理解
507348
__vector__楼主2022/7/28 16:23

我是看的第二篇题解。
我写的代码:

#include <bits/stdc++.h>
using namespace std;
namespace Main
{
    typedef long long ll;
    typedef __int128 ll128;
    const int maxn=1e5+5;
    struct OD
    {
        int x,y1,y2;
        int flag;//权值
        //x是纵线的横坐标,y1是下纵坐标,y2是上纵坐标
    }od[maxn<<1],lsh[maxn<<1];
    //od存储原始读入的竖线信息,lsh存储横坐标不变,纵坐标离散化之后的信息
    int n;
    int h_rem[maxn<<1];//暂时存储纵坐标相关信息
    inline bool cmp(OD a,OD b)
    {
        return (a.x!=b.x)?(a.x<b.x):(a.flag>b.flag);
    }
    struct Tree
    {
        int l,r,ls,rs,len,lazy;
    }tree[maxn*16];//nlogn*2
    int val[maxn<<1];
    int ncnt;
    inline int ls(int i)
    {
        return tree[i].ls;
    }
    inline int rs(int i)
    {
        return tree[i].rs;
    }
    inline int len(int i)
    {
        return tree[i].r-tree[i].l+1;
    }
    inline void add(int i,int val)
    {
        tree[i].lazy+=val;
    }
    inline void push_up(int i)
    {
        if(tree[i].lazy)
        {
            tree[i].len=val[tree[i].r+1]-val[tree[i].l];
            return;
        }
        tree[i].len=tree[ls(i)].len+tree[rs(i)].len;
    }
    int build(int i,int l,int r)
    {
        i=++ncnt;
        tree[i].l=l,tree[i].r=r;
        if(l==r)return i;
        int mid=(l+r)>>1;
        tree[i].ls=build(ls(i),l,mid);
        tree[i].rs=build(rs(i),mid+1,r);
        return i;
    }
    inline void modify(int i,int l,int r,int val)
    {
        if(tree[i].l>=l&&tree[i].r<=r)
        {
            add(i,val);
            push_up(i);
            return;
        }
        if(tree[i].r<l||tree[i].l>r)return;
        int mid=(tree[i].l+tree[i].r)>>1;
        if(mid>=l)modify(ls(i),l,r,val);
        if(mid<r)modify(rs(i),l,r,val);
        push_up(i);
    }
    void main()
    {
        scanf("%d",&n);

        int x_1,y_1,x_2,y_2;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&x_1,&y_1,&x_2,&y_2);
            od[i].x=x_1,od[i].y1=y_1,od[i].y2=y_2,od[i].flag=1;
            od[i+n].x=x_2,od[i+n].y1=y_1,od[i+n].y2=y_2,od[i+n].flag=-1;
            h_rem[i]=y_1;
            h_rem[i+n]=y_2;
        }
        sort(h_rem+1,h_rem+2*n+1);
        int tot=unique(h_rem+1,h_rem+2*n+1)-h_rem-1;
        for(int i=1;i<=2*n;i++)
        {
            lsh[i].x=od[i].x;
            lsh[i].flag=od[i].flag;
            lsh[i].y1=lower_bound(h_rem+1,h_rem+tot+1,od[i].y1)-h_rem;
            lsh[i].y2=lower_bound(h_rem+1,h_rem+tot+1,od[i].y2)-h_rem;
            val[lsh[i].y1]=od[i].y1;
            val[lsh[i].y2]=od[i].y2;
        }
        sort(lsh+1,lsh+2*n+1,cmp);
        int rt=build(1,1,2*n);//y的排名最多到tot
        ll128 ans=0;
        for(int i=1;i<2*n;i++)
        {
            modify(1,lsh[i].y1,lsh[i].y2-1,lsh[i].flag);
            ans+=(ll128)tree[1].len*(ll128)(lsh[i+1].x-lsh[i].x);
        }
        printf("%lld",(ll)ans);
    }
}
int main()
{
    Main::main();
    return 0;
}

为什么第 105105 行,要把竖线的上 yy 坐标离散化后的值减一再进行修改(lsh[i].y2-1

为什么第 4747 行,push_up 的时候,要先把当前区间的右端点加一再计算(val[tree[i].r+1]

2022/7/28 16:23
加载中...