题解 [CF793F] Julia the snail
真切感受到了讲课就是被带着颓题解(
我去扫大街扫描线,尝试对每个 \(r\) 维护出 \(f(l)\) 表示 \(l\) 处的答案
那么加入一条绳子 \([l, r]\) 的影响就是将 \(f(i)\geqslant l\) 的 \(f(i)\) 赋值为 \(r\)
注意还有一个绳子必须要完全在这个区间中的限制
所以其实是将 \(i\leqslant l\and f(i)\geqslant l\) 的 \(f(i)\) 均赋为 \(r\)
这个东西可以用 \(\tt SegmentBeats\) 来做
但是还有更简单的做法:
直接写懒标记,标记是可以合并的
考虑当某时刻下放标记时若 \(f(i)<l\),则其实际意义是绳子已经无交,即蜗牛不可能爬上来了
那么新的标记已经无用,不必下放了
否则合并是容易的
这个做法可行本质上是依赖了扫描线后 \(r\) 是单调的
复杂度 \(O((n+m)\log n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m, q;
int ans[N];
bool isleaf[N<<2];
vector<int> add[N];
#define tl(p) tl[p]
#define tr(p) tr[p]
pair<int, int> tag[N<<2];
vector<pair<int, int>> que[N];
int tl[N<<2], tr[N<<2], val[N<<2];
const pair<int, int> nulltag={0, 0};
void spread(int p, pair<int, int> dat) {
if (isleaf[p]) {if (val[p]>=dat.fir) val[p]=dat.sec;}
else if (tag[p]==nulltag) tag[p]=dat;
else if (dat.fir<=tag[p].fir) tag[p]=dat;
else if (dat.fir<=tag[p].sec) tag[p].sec=dat.sec;
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) {isleaf[p]=1; val[p]=l; return ;}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void upd(int p, int l, int r, pair<int, int> dat) {
if (l<=tl(p)&&r>=tr(p)) {spread(p, dat); return ;}
if (tag[p]!=nulltag) spread(p<<1, tag[p]), spread(p<<1|1, tag[p]), tag[p]=nulltag;
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) upd(p<<1, l, r, dat);
if (r>mid) upd(p<<1|1, l, r, dat);
}
int query(int p, int pos) {
if (tl(p)==tr(p)) return val[p];
if (tag[p]!=nulltag) spread(p<<1, tag[p]), spread(p<<1|1, tag[p]), tag[p]=nulltag;
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) return query(p<<1, pos);
else return query(p<<1|1, pos);
}
signed main()
{
n=read(); m=read();
for (int i=1,l,r; i<=m; ++i) {
l=read(); r=read();
add[r].pb(l);
}
q=read();
for (int i=1,l,r; i<=q; ++i) {
l=read(); r=read();
que[r].pb({l, i});
}
build(1, 1, n);
for (int i=1; i<=n; ++i) {
for (auto it:add[i]) upd(1, 1, it, {it, i});
for (auto it:que[i]) ans[it.sec]=query(1, it.fir);
}
for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
return 0;
}