『学习笔记』扫描线(todo)

降维

P5490 【模板】扫描线 & 矩形面积并

【学习笔记】扫描线 - 洛谷专栏

离散化后线段树维护当前覆盖区间长度并计算答案。

需要注意的是线段树的叶子结点不能表示数轴上的一个点,要表示一段区间。所以可以令线段树上的 \([l,r]\) 表示实际上的 \([l,r+1]\) (离散化后)。

typedef long long ll;
const int N=1e5+5;
int n;
ll X[N<<1];
struct Op{
    ll x1,x2,y,mark;
    bool operator<(Op a){return y==a.y ? x1<a.x1 : y<a.y;}
}op[N<<1];

class SgT{
    public:
        void build(int rt,int l,int r){
            t[rt].l=l,t[rt].r=r,t[rt].len=t[rt].tag=0;
            if(l==r) return;
            int mid=l+r>>1;
            build(ls(rt),l,mid);
            build(rs(rt),mid+1,r);
        }
        void update(int rt,ll l,ll r,int x){
            if(l<=t[rt].l && t[rt].r<=r){
                t[rt].tag+=x;
                pushup(rt);
                return;
            }
            int mid=t[rt].l+t[rt].r>>1;
            if(l<=mid) update(ls(rt),l,r,x);
            if(r>mid) update(rs(rt),l,r,x);
            pushup(rt);
        }
        int query(){return t[1].len;}
    private:
        struct node{
            int l,r;
            int len,tag;
        }t[N<<5];
        inline int ls(int rt){return rt<<1;}
        inline int rs(int rt){return rt<<1|1;}
        inline void pushup(int rt){
            int l=t[rt].l,r=t[rt].r;
            if(t[rt].tag) t[rt].len=X[r+1]-X[l];
            else t[rt].len=t[ls(rt)].len+t[rs(rt)].len;
        }
}t;

int main(){
    n=read();
    for(int i=1; i<=n; i++){
        int x1=read(),y1=read(),x2=read(),y2=read();
        X[(i<<1)-1]=x1,X[i<<1]=x2;
        op[(i<<1)-1]={x1,x2,y1,1},op[i<<1]={x1,x2,y2,-1};
    }
    n<<=1;
    sort(op+1,op+n+1);
    sort(X+1,X+n+1);
    int L=unique(X+1,X+n+1)-X-1;
    t.build(1,1,L-1);
    ll ans=0;
    for(int i=1; i<n; i++){
        t.update(1,lower_bound(X+1,X+L+1,op[i].x1)-X,
            lower_bound(X+1,X+L+1,op[i].x2)-X-1,op[i].mark);
        ans+=t.query()*(op[i+1].y-op[i].y);
    }
    printf("%lld\n",ans);
    return 0;
}

记录详情

P9871 [NOIP2023] 天天爱打卡

一共有 \(n\) 天,可以花费 \(d\) 的能量在任何一天跑步,但不能在连续的 \(k\) 天跑步。给出 \(m\) 段任务区间 \([l_i,r_i]\),若这段区间每天都跑了步,获得 \(v_i\) 能量。求最终能量最大值。

\(f_i\) 表示第 \(i\) 天跑步,前 \(i\) 天最大能量。枚举上一次不跑步的时候,看最后跑步的这段区间包含了那些区间,扫描线。

只需要保留 \(l-1,l,r\),离散化 dp,转移线段树优化,\(O(n \log n)\)

P1972 [SDOI2009] HH的项链

给出长度为 \(n\) 的序列 \(a_i\)\(q\) 次询问区间 \([l,r]\) 中多少个不同的 \(a_i\)(即数颜色)。\(1 \le n \le 10^6\)

离线:\(pre_i\) 表示 \(i\) 之前与 \(a_i\) 相等的数。树状数组统计 \([l,r]\)\(pre_i<l\) 的个数与 \([1,l-1]\) 的即可。

在线:主席树。

给定 \(n\) 个点的树,\(q\) 次查询当树上仅剩编号为 \([l,r]\) 的点和边时连通块个数。\(1 \le n \le 10^6\)

答案即为点数减去端点均在 \([l,r]\) 内的边数。

对于每条边,将其看为 \([min(u,v,id),max(u,v,id)]\),扫描线统计被完全包含的区间。

给定许多模式字符串,每次查询给定 \(s_1,s_2\),求前缀为 \(s_1\),后缀为 \(s_2\) 的模式串数量。

CF703D Mishka and Interesting sum

给定一个序列,每次查询区间中出现偶数次的数的异或和。

P8512 [Ynoi Easy Round 2021] TEST_152

给定 \(n\) 次操作 \((l_i,r_i,v_i)\)\(q\) 次询问每次对一个初始全 \(0\) 的长度为 \(m\) 的序列 \(c\) 进行 \([l,r]\) 次操作,每次将 \([l_i,r_i]\) 赋值为 \(v_i\),最终 \(c\) 的和。

posted @ 2025-01-05 22:12  仙山有茗  阅读(44)  评论(0)    收藏  举报