『学习笔记』扫描线(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\) 的和。

浙公网安备 33010602011771号