整体二分做题记录
0.前言
1.5 年前学过,没学好,回来加训。
I.P3834 【模板】可持久化线段树 2
板子题。时间复杂度 \(\mathcal{O(n \log^2 n)}\)。把 \(\{a_i\}\) 看作修改和后面的询问放一起,每次二分出答案值域上的 \(mid\) 后,如果修改的值 \(\le mid\),那么 BIT 在 \(i\) 这个点上加 \(1\);如果是询问,那么询问 BIT 上 \([l,r]\) 中 \(1\) 的个数,和 \(k\) 进行比较,判断是分到左边分治还是右边。
#include <bits/stdc++.h>
// #define int long long
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
#define rep(i,l,r) for (int i = (int)(l); i <= (int)(r); ++ i )
#define rep1(i,l,r) for (int i = (int)(l); i >= (int)(r); -- i )
#define il inline
#define fst first
#define snd second
#define ptc putchar
#define Yes ptc('Y'),ptc('e'),ptc('s'),puts("")
#define No ptc('N'),ptc('o'),puts("")
#define YES ptc('Y'),ptc('E'),ptc('S'),puts("")
#define NO ptc('N'),ptc('O'),puts("")
#define vi vector<int>
#define pb emplace_back
#define sz(x) (int)(x.size())
#define all(x) x.begin(),x.end()
#define me(a,x) memset(a,x,sizeof a)
#define get(x) ((x - 1) / len + 1)
#define debug() puts("------------")
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<ll,ll> PLL;
namespace szhqwq {
template<class T> il void read(T &x) {
x = 0; T f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
template<class T,class... Args> il void read(T &x,Args &...x_) { read(x); read(x_...); }
template<class T> il void print(T x) {
if (x < 0) ptc('-'), x = -x;
if (x > 9) print(x / 10); ptc(x % 10 + '0');
}
template<class T,class T_> il void write(T x,T_ ch) { print(x); ptc(ch); }
template<class T,class T_> il void chmax(T &x,T_ y) { x = x < (T)y ? (T)y : x; }
template<class T,class T_> il void chmin(T &x,T_ y) { x = x > (T)y ? (T)y : x; }
template<class T,class T_,class T__> il T qmi(T a,T_ b,T__ p) {
T res = 1; while (b) {
if (b & 1) res = res * a % p;
a = a * a % p; b >>= 1;
} return res;
}
template<class T,class T_> il T qmi(T a,T_ b) {
T res = 1; while (b) {
if (b & 1) res = res * a;
a = a * a; b >>= 1;
} return res;
}
template<class T> il T gcd(T a,T b) { if (!b) return a; return gcd(b,a % b); }
template<class T,class T_> il void exgcd(T a, T b, T_ &x, T_ &y) {
if (b == 0) { x = 1; y = 0; return; }
exgcd(b,a % b,y,x); y -= a / b * x; return ;
}
template<class T,class T_> il T getinv(T x,T_ p) {
T inv,y; exgcd(x,(T)p,inv,y);
inv = (inv + p) % p; return inv;
}
} using namespace szhqwq;
const int N = 4e5 + 10,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
const db eps = 1e-6;
int n,m,lim,a[N],ret[N],tot; vi v;
struct node {
int l,r,k;
int tp,id;
} p[N],pl[N],pr[N];
struct BIT {
int tr[N];
il void add(int x,int k) {
for (; x <= lim; x += x & -x) tr[x] += k;
}
il int query(int x) {
int ret = 0;
for (; x; x -= x & -x) ret += tr[x];
return ret;
}
} bit;
il void aaa(int l,int r,int L,int R) {
if (l > r || L > R) return ;
if (l == r) {
rep(i,L,R) if (p[i].tp) ret[p[i].id] = l;
return ;
}
int mid = l + r >> 1,le = 0,ri = 0;
rep(i,L,R) {
if (!p[i].tp) {
if (p[i].l <= mid) bit.add(p[i].id,1),pl[++ le] = p[i];
else pr[++ ri] = p[i];
} else {
int val = bit.query(p[i].r) - bit.query(p[i].l - 1);
if (p[i].k <= val) pl[++ le] = p[i];
else p[i].k -= val,pr[++ ri] = p[i];
}
}
rep(i,1,le) if (!pl[i].tp) bit.add(pl[i].id,-1);
rep(i,1,le) p[i + L - 1] = pl[i];
rep(i,1,ri) p[i + L + le - 1] = pr[i];
aaa(l,mid,L,L + le - 1); aaa(mid + 1,r,L + le,R);
return ;
}
il void solve() {
//------------code------------
read(n,m); lim = n;
rep(i,1,n) read(a[i]),v.pb(a[i]);
sort(all(v)); v.erase(unique(all(v)),v.end());
rep(i,1,n) a[i] = lower_bound(all(v),a[i]) - v.begin() + 1;
rep(i,1,n) p[++ tot] = {a[i],0,0,0,i};
rep(i,1,m) {
int l,r,k; read(l,r,k);
p[++ tot] = {l,r,k,1,i};
}
aaa(1,sz(v),1,tot);
rep(i,1,m) write(v[ret[i] - 1],'\n');
return ;
}
il void init() {
return ;
}
signed main() {
// init();
int _ = 1;
// read(_);
while (_ -- ) solve();
return 0;
}
II.P3527 MET-Meteors
考虑破环成链,然后正常整体二分套树状数组维护即可。
#include <bits/stdc++.h>
// #define int long long
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
#define rep(i,l,r) for (int i = (int)(l); i <= (int)(r); ++ i )
#define rep1(i,l,r) for (int i = (int)(l); i >= (int)(r); -- i )
#define il inline
#define fst first
#define snd second
#define ptc putchar
#define Yes ptc('Y'),ptc('e'),ptc('s'),puts("")
#define No ptc('N'),ptc('o'),puts("")
#define YES ptc('Y'),ptc('E'),ptc('S'),puts("")
#define NO ptc('N'),ptc('O'),puts("")
#define vi vector<int>
#define pb emplace_back
#define sz(x) (int)(x.size())
#define all(x) x.begin(),x.end()
#define me(a,x) memset(a,x,sizeof a)
#define get(x) ((x - 1) / len + 1)
#define debug() puts("------------")
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<ll,ll> PLL;
namespace szhqwq {
template<class T> il void read(T &x) {
x = 0; T f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
template<class T,class... Args> il void read(T &x,Args &...x_) { read(x); read(x_...); }
template<class T> il void print(T x) {
if (x < 0) ptc('-'), x = -x;
if (x > 9) print(x / 10); ptc(x % 10 + '0');
}
template<class T,class T_> il void write(T x,T_ ch) { print(x); ptc(ch); }
template<class T,class T_> il void chmax(T &x,T_ y) { x = x < (T)y ? (T)y : x; }
template<class T,class T_> il void chmin(T &x,T_ y) { x = x > (T)y ? (T)y : x; }
template<class T,class T_,class T__> il T qmi(T a,T_ b,T__ p) {
T res = 1; while (b) {
if (b & 1) res = res * a % p;
a = a * a % p; b >>= 1;
} return res;
}
template<class T> il T gcd(T a,T b) { if (!b) return a; return gcd(b,a % b); }
template<class T,class T_> il void exgcd(T a, T b, T_ &x, T_ &y) {
if (b == 0) { x = 1; y = 0; return; }
exgcd(b,a % b,y,x); y -= a / b * x; return ;
}
template<class T,class T_> il T getinv(T x,T_ p) {
T inv,y; exgcd(x,(T)p,inv,y);
inv = (inv + p) % p; return inv;
}
} using namespace szhqwq;
const int N = 2e5 + 10,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
const db eps = 1e-6;
int n,m,k;
vector<int> a[N];
int res[N];
struct node { int x,id; } q[N],q1[N],q2[N];
struct cg { int l,r,x,id; } c[N];
struct BIT {
int tr[N];
il void add(int x,int k) {
for (; x <= (m << 1); x += x & -x) tr[x] += k;
}
il int query(int x) {
int ret = 0;
for (; x; x -= x & -x) ret += tr[x];
return ret;
}
} bit;
il void aaa(int l,int r,int ql,int qr) {
if (ql > qr) return ;
if (l == r) {
rep(i,ql,qr) res[q[i].id] = l;
return ;
}
int mid = l + r >> 1;
int cnt1 = 0,cnt2 = 0;
rep(i,l,mid) bit.add(c[i].l,c[i].x),bit.add(c[i].r + 1,-c[i].x);
rep(i,ql,qr) {
int t = 0;
for (auto x : a[q[i].id]) {
t += bit.query(x) + bit.query(x + m);
if (t >= q[i].x) break;
}
if (q[i].x <= t) q1[++ cnt1] = q[i];
else q[i].x -= t,q2[++ cnt2] = q[i];
}
rep(i,l,mid) bit.add(c[i].l,-c[i].x),bit.add(c[i].r + 1,c[i].x);
rep(i,1,cnt1) q[i + ql - 1] = q1[i];
rep(i,1,cnt2) q[i + ql + cnt1 - 1] = q2[i];
aaa(l,mid,ql,ql + cnt1 - 1);
aaa(mid + 1,r,ql + cnt1,qr);
}
il void solve() {
//------------code------------
read(n,m);
rep(i,1,m) {
int x; read(x);
a[x].pb(i);
}
int idx = 0;
rep(i,1,n) {
int p; read(p);
q[++ idx] = {p,i};
}
read(k);
rep(i,1,k) {
read(c[i].l,c[i].r,c[i].x);
c[i].id = i;
if (c[i].l > c[i].r) c[i].r += m;
}
c[++ k] = {1,m << 1,inf};
aaa(1,k,1,idx);
rep(i,1,n) {
if (res[i] < k) write(res[i],'\n');
else puts("NIE");
}
return ;
}
il void init() {
return ;
}
signed main() {
// init();
int _ = 1;
// read(_);
while (_ -- ) solve();
return 0;
}
III.P1527 矩阵乘法
考虑使用二维树状数组维护即可。代码是以前写的。就不放了。
IV.P3332 K大数查询
因为维护的是可重集,所以向 \([l,r]\) 的可重集中加入编号 \(c\) 的数可直接看作 \([l,r]\) 的可重集中数字个数加一。然后就做完了。
V.P4175 网络管理
当然可以大力树剖。
考虑更好写的做法,树状数组上维护根到当前节点上 \(1\) 的个数,只需要把树拍到 dfs 序上,对子树进行区间加,查询可以看作树上差分,预处理维护一个 LCA,然后就做完了。
注意判断无解的情况,当且仅当 \(u \to v\) 路径长度不足 \(k\)。
#include <bits/stdc++.h>
// #define int long long
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
#define rep(i,l,r) for (int i = (int)(l); i <= (int)(r); ++ i )
#define rep1(i,l,r) for (int i = (int)(l); i >= (int)(r); -- i )
#define il inline
#define fst first
#define snd second
#define ptc putchar
#define Yes ptc('Y'),ptc('e'),ptc('s'),puts("")
#define No ptc('N'),ptc('o'),puts("")
#define YES ptc('Y'),ptc('E'),ptc('S'),puts("")
#define NO ptc('N'),ptc('O'),puts("")
#define vi vector<int>
#define pb emplace_back
#define sz(x) (int)(x.size())
#define all(x) x.begin(),x.end()
#define me(a,x) memset(a,x,sizeof a)
#define get(x) ((x - 1) / len + 1)
#define debug() puts("------------")
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<ll,ll> PLL;
namespace szhqwq {
template<class T> il void read(T &x) {
x = 0; T f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
template<class T,class... Args> il void read(T &x,Args &...x_) { read(x); read(x_...); }
template<class T> il void print(T x) {
if (x < 0) ptc('-'), x = -x;
if (x > 9) print(x / 10); ptc(x % 10 + '0');
}
template<class T,class T_> il void write(T x,T_ ch) { print(x); ptc(ch); }
template<class T,class T_> il void chmax(T &x,T_ y) { x = x < (T)y ? (T)y : x; }
template<class T,class T_> il void chmin(T &x,T_ y) { x = x > (T)y ? (T)y : x; }
template<class T,class T_,class T__> il T qmi(T a,T_ b,T__ p) {
T res = 1; while (b) {
if (b & 1) res = res * a % p;
a = a * a % p; b >>= 1;
} return res;
}
template<class T> il T gcd(T a,T b) { if (!b) return a; return gcd(b,a % b); }
template<class T,class T_> il void exgcd(T a, T b, T_ &x, T_ &y) {
if (b == 0) { x = 1; y = 0; return; }
exgcd(b,a % b,y,x); y -= a / b * x; return ;
}
template<class T,class T_> il T getinv(T x,T_ p) {
T inv,y; exgcd(x,(T)p,inv,y);
inv = (inv + p) % p; return inv;
}
} using namespace szhqwq;
const int N = 2e5 + 10,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
const db eps = 1e-6;
int n,q,t[N],tot,ret[N];
int h[N],e[N],ne[N],idx;
int id[N],cnt,fa[N][20],d[N],siz[N];
struct Q { int a,b,k; } c[N];
struct node {
int l,r,k;
int tp,id;
} p[N],pl[N],pr[N];
int lim;
struct BIT {
int tr[N];
il void add(int x,int k) {
for (; x <= lim; x += x & -x) tr[x] += k;
}
il int query(int x) {
int ret = 0;
for (; x; x -= x & -x) ret += tr[x];
return ret;
}
} bit;
il void add(int a,int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
il void dfs(int u,int f) {
fa[u][0] = f; id[u] = ++ cnt;
d[u] = d[f] + 1; siz[u] = 1;
rep(i,1,18) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == f) continue;
dfs(j,u);
siz[u] += siz[j];
}
}
il int lca(int x,int y) {
if (d[x] < d[y]) swap(x,y);
rep1(i,18,0) if (d[fa[x][i]] >= d[y]) x = fa[x][i];
if (x == y) return x;
rep1(i,18,0) if (fa[x][i] != fa[y][i]) x = fa[x][i],y = fa[y][i];
return fa[x][0];
}
il void aaa(int l,int r,int L,int R) {
if (l > r || L > R) return ;
if (l == r) {
// if (L <= 5 && R >= 5) cerr << l << " " << r << '\n';
rep(i,L,R) if (p[i].tp) ret[p[i].id] = l;
return ;
}
int mid = l + r >> 1,le = 0,ri = 0;
rep(i,L,R) {
if (!p[i].tp) {
if (p[i].l > mid) bit.add(id[p[i].id],p[i].r),bit.add(id[p[i].id] + siz[p[i].id] - 1 + 1,-p[i].r),pr[++ ri] = p[i];
else pl[++ le] = p[i];
} else {
int pp = lca(p[i].l,p[i].r);
// cerr << "lca " << p[i].l << " " << p[i].r << " " << pp << '\n';
int val = bit.query(id[p[i].l]) + bit.query(id[p[i].r]) - bit.query(id[pp]) - bit.query(id[fa[pp][0]]);
if (p[i].k <= val) pr[++ ri] = p[i];
else p[i].k -= val,pl[++ le] = p[i];
}
}
rep(i,1,ri) if (!pr[i].tp) bit.add(id[pr[i].id],-pr[i].r),bit.add(id[pr[i].id] + siz[pr[i].id] - 1 + 1,pr[i].r);
rep(i,1,le) p[i + L - 1] = pl[i];
rep(i,1,ri) p[i + L + le - 1] = pr[i];
aaa(l,mid,L,L + le - 1); aaa(mid + 1,r,L + le,R);
return ;
}
il void solve() {
//------------code------------
read(n,q); vi v; lim = n; me(h,-1);
rep(i,1,n) read(t[i]),v.pb(t[i]);
rep(i,1,n - 1) {
int a,b; read(a,b);
add(a,b); add(b,a);
}
dfs(1,0);
rep(i,1,q) {
read(c[i].k,c[i].a,c[i].b);
if (!c[i].k) v.pb(c[i].b);
ret[i] = -1;
}
sort(all(v)); v.erase(unique(all(v)),v.end());
rep(i,1,n) t[i] = lower_bound(all(v),t[i]) - v.begin() + 1;
rep(i,1,q) if (!c[i].k) c[i].b = lower_bound(all(v),c[i].b) - v.begin() + 1;
rep(i,1,n) p[++ tot] = {t[i],1,0,0,i};
rep(i,1,q)
if (!c[i].k) {
p[++ tot] = {t[c[i].a],-1,0,0,c[i].a};
p[++ tot] = {c[i].b,1,0,0,c[i].a};
t[c[i].a] = c[i].b;
} else p[++ tot] = {c[i].a,c[i].b,c[i].k,1,i};
aaa(1,sz(v),1,tot);
rep(i,1,q) if (c[i].k) {
int pp = lca(c[i].a,c[i].b);
int val = d[c[i].a] + d[c[i].b] - d[pp] - d[fa[pp][0]];
if (c[i].k <= val) write(v[ret[i] - 1],'\n');
else puts("invalid request!");
}
return ;
}
il void init() {
return ;
}
signed main() {
// init();
int _ = 1;
// read(_);
while (_ -- ) solve();
return 0;
}
VI.P7424 天天爱射击
考虑将子弹看作修改,木板看作询问,记录每个木板是被哪颗子弹打碎的,具体的,将整体二分的答案值域设为 \([1,m + 1]\),如果这个木板的答案是 \(m + 1\),证明到最后它都不会碎掉,然后就做完了。
时间复杂度 \(\mathcal{O(n \log^2 n)}\),写主席树 + 二分同样是 \(\mathcal{O(n \log^2 n)}\) 的,不过常数巨大。通过主席树上二分可以做到单 \(\log\)。
因为复习整体二分,所以还是写的整体二分。111
#include <bits/stdc++.h>
// #define int long long
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
#define rep(i,l,r) for (int i = (int)(l); i <= (int)(r); ++ i )
#define rep1(i,l,r) for (int i = (int)(l); i >= (int)(r); -- i )
#define il inline
#define fst first
#define snd second
#define ptc putchar
#define Yes ptc('Y'),ptc('e'),ptc('s'),puts("")
#define No ptc('N'),ptc('o'),puts("")
#define YES ptc('Y'),ptc('E'),ptc('S'),puts("")
#define NO ptc('N'),ptc('O'),puts("")
#define vi vector<int>
#define pb emplace_back
#define sz(x) (int)(x.size())
#define all(x) x.begin(),x.end()
#define me(a,x) memset(a,x,sizeof a)
#define get(x) ((x - 1) / len + 1)
#define debug() puts("------------")
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<ll,ll> PLL;
namespace szhqwq {
template<class T> il void read(T &x) {
x = 0; T f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
template<class T,class... Args> il void read(T &x,Args &...x_) { read(x); read(x_...); }
template<class T> il void print(T x) {
if (x < 0) ptc('-'), x = -x;
if (x > 9) print(x / 10); ptc(x % 10 + '0');
}
template<class T,class T_> il void write(T x,T_ ch) { print(x); ptc(ch); }
template<class T,class T_> il void chmax(T &x,T_ y) { x = x < (T)y ? (T)y : x; }
template<class T,class T_> il void chmin(T &x,T_ y) { x = x > (T)y ? (T)y : x; }
template<class T,class T_,class T__> il T qmi(T a,T_ b,T__ p) {
T res = 1; while (b) {
if (b & 1) res = res * a % p;
a = a * a % p; b >>= 1;
} return res;
}
template<class T> il T gcd(T a,T b) { if (!b) return a; return gcd(b,a % b); }
template<class T,class T_> il void exgcd(T a, T b, T_ &x, T_ &y) {
if (b == 0) { x = 1; y = 0; return; }
exgcd(b,a % b,y,x); y -= a / b * x; return ;
}
template<class T,class T_> il T getinv(T x,T_ p) {
T inv,y; exgcd(x,(T)p,inv,y);
inv = (inv + p) % p; return inv;
}
} using namespace szhqwq;
const int N = 4e5 + 10,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
const db eps = 1e-6;
vi v; struct Q { int l,r,k; } c[N];
int n,m,tot,lim,ret[N],a[N];
struct node {
int l,r,k;
int tp,id;
} p[N],pl[N],pr[N];
int res[N];
struct BIT {
int tr[N];
il void add(int x,int k) {
for (; x <= lim; x += x & -x) tr[x] += k;
}
il int query(int x) {
int ret = 0;
for (; x; x -= x & -x) ret += tr[x];
return ret;
}
} bit;
il void aaa(int l,int r,int L,int R) {
if (l > r || L > R) return ;
if (l == r) {
rep(i,L,R) if (p[i].tp) ret[p[i].id] = l;
return ;
}
int mid = l + r >> 1,le = 0,ri = 0;
rep(i,L,R) {
if (!p[i].tp) {
if (p[i].l <= mid) bit.add(p[i].id,p[i].r),pl[++ le] = p[i];
else pr[++ ri] = p[i];
} else {
int val = bit.query(p[i].r) - bit.query(p[i].l - 1);
if (p[i].k <= val) pl[++ le] = p[i];
else p[i].k -= val,pr[++ ri] = p[i];
}
}
rep(i,1,le) if (!pl[i].tp) bit.add(pl[i].id,-pl[i].r);
rep(i,1,le) p[i + L - 1] = pl[i];
rep(i,1,ri) p[i + L + le - 1] = pr[i];
aaa(l,mid,L,L + le - 1); aaa(mid + 1,r,L + le,R);
return ;
}
il void solve() {
//------------code------------
read(n,m);
rep(i,1,n) read(c[i].l,c[i].r,c[i].k),chmax(lim,c[i].r);
rep(i,1,m) read(a[i]),p[++ tot] = {i,1,0,0,a[i]},chmax(lim,a[i]);
rep(i,1,n) p[++ tot] = {c[i].l,c[i].r,c[i].k,1,i};
aaa(1,m + 1,1,tot);
rep(i,1,n) if (ret[i] <= m) ++ res[ret[i]];
rep(i,1,m) write(res[i],'\n');
return ;
}
il void init() {
return ;
}
signed main() {
// init();
int _ = 1;
// read(_);
while (_ -- ) solve();
return 0;
}
待续。。