資料結構
- 權值 BIT 上二分
struct {
int n,t[N];
int kth(int k) {
int p = 0;
rFor(i,__lg(n),0) if( p+(1<<i) < n && k > t[p+(1<<i)] ) p += 1<<i, k -= t[p];
return p+1;
}
} ;
-
zkw 線段樹
-
李超線段樹
-
線段樹合併,分裂
-
可持久化 \(01\)Trie
值域 \([0,2^{30})\)
struct {
int ind,rt[N],ch[N*31][2],siz[N*31];
void ins(int u,int v,int x) {
u = rt[u], v = rt[v] = ++ind;
rFor(i,29,0) {
bool y = x>>i&1;
ch[v][!y] = ch[u][!y], u = ch[u][y], v = ch[v][y] = ++ind,
siz[v] = siz[u] + 1;
}
}
int qry(int u,int v,int x) {
u = rt[u], v = rt[v];
int res = 0;
for(int i = 1<<29; i; i >>= 1) {
bool y = ~x&i;
if( siz[ch[u][y]] < siz[ch[v][y]] ) res |= i, u = ch[u][y], v = ch[v][y];
else u = ch[u][!y], v = ch[v][!y];
}
return res;
}
} ;
- 笛卡爾樹
升序 BST 以 \(i\) 為權值,小根堆以 \(a[i]\) 為權值
void bld() {
For(i,1,n) {
int tmp = tp;
while( tp && a[i] < a[stk[tp]] ) --tp;
if( tp ) ch[stk[tp]][1] = i;
if( tp < tmp ) ch[i][0] = stk[tp+1];
stk[++tp] = i;
}
}
- 可持久化文藝平衡樹
空間限制 \(256\)MB
// LG5586 [P5350] 序列 (加強版)
#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
const int N = 3e5+5, M = 5e6;
int ind,rt,n,a[N],len[N];
struct Node { int ch[2],siz,len; mint val,sum,add; bool rev; } t[M+N];
int node(int len,mint x)
{ return t[++ind] = {0,0,len,len,x,len*x,0,0}, ind; }
int node(const Node &x){ return t[++ind] = x, ind; }
void up(int u) {
t[u].siz = t[ls(u)].siz + t[rs(u)].siz + t[u].len,
t[u].sum = t[ls(u)].sum + t[rs(u)].sum + t[u].len*t[u].val;
}
void down(int u,mint x,bool y) {
if( x.x ) t[u].val += x, t[u].add += x, t[u].sum += t[u].siz * x;
if( y ) t[u].rev ^= y, swap(ls(u),rs(u));
}
void down(int u) { if( t[u].add.x || t[u].rev ) {
if( ls(u) ) down( ls(u)=node(t[ls(u)]) ,t[u].add,t[u].rev);
if( rs(u) ) down( rs(u)=node(t[rs(u)]) ,t[u].add,t[u].rev);
t[u].add = t[u].rev = 0;
}}
void dfs(int u) {
down(u);
if( ls(u) ) dfs(ls(u));
if( n && a[n] == t[u].val.x ) len[n] += t[u].len;
else a[++n] = t[u].val.x, len[n] = t[u].len;
if( rs(u) ) dfs(rs(u));
}
int bld(int l=1,int r=n) {
if( l > r ) return 0;
int mid = l+r>>1, u = node(len[mid],a[mid]);
return ls(u) = bld(l,mid-1), rs(u) = bld(mid+1,r), up(u), u;
}
void rbld() { n = 0, dfs(rt), ind = 0, rt = bld(); }
void split(int u,int k,int &l,int &r) {
if( !u ) { l = r = 0; return; }
down(u);
if( t[ls(u)].siz < k && k < t[ls(u)].siz+t[u].len ) {
int mid = k-t[ls(u)].siz, v = node(t[u]);
t[v].len = t[u].len-mid, t[u].len = mid;
ls(v) = 0, rs(u) = v, up(v), up(u);
}
if( k <= t[ls(u)].siz ) r = node(t[u]), split(ls(r),k,l,ls(r)), up(r);
else l = node(t[u]), split(rs(l),k-t[ls(l)].siz-t[l].len,rs(l),r), up(l);
}
int merge(int l,int r) {
if( !l || !r ) return l | r;
int u;
if( mt()%(t[l].siz+t[r].siz) < t[l].siz )
down(u=node(t[l])), rs(u) = merge(rs(u),r);
else down(u=node(t[r])), ls(u) = merge(l,ls(u));
return up(u), u;
}
mint sum(int l,int r) { // ask sum of [l,r]
int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
mint res = t[b].sum;
rt = merge(merge(a,b),c);
return res;
}
void cov(int l,int r,int x) { // let [l,r] = x
int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
rt = merge(merge(a,node(r-l+1,x)),c);
}
void add(int l,int r,int x) { // let [l,r] += x
int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
down(b,x,0);
rt = merge(merge(a,b),c);
}
void copy(int l1,int r1,int l2,int r2) { // let [l2,r2] = [l1,r1]
int a,b,c,d,e; bool flg = 0;
if( l1 > l2 ) swap(l1,l2), swap(r1,r2), flg = 1;
split(rt,r2,d,e), split(d,l2-1,c,d), split(c,r1,b,c), split(b,l1-1,a,b);
rt = merge(merge(merge(merge(a,!flg?b:d),c),!flg?b:d),e);
}
void swap(int l1,int r1,int l2,int r2) { // swap [l1,r1] and [l2,r2]
if( l1 > l2 ) swap(l1,l2), swap(r1,r2);
int a,b,c,d,e;
split(rt,r2,d,e), split(d,l2-1,c,d), split(c,r1,b,c), split(b,l1-1,a,b);
rt = merge(merge(merge(merge(a,d),c),b),e);
}
void rev(int l,int r) { // reverse [l,r]
int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
down(b,0,1);
rt = merge(merge(a,b),c);
}
void dbg() {
n = 0, dfs(rt);
For(i,1,n, p = 1) {
if( len[i] > 1 ) cerr<<"["<<p<<","<<p+len[i]-1<<"]:";
cerr<<a[i]<<(i<n?' ':'\n');
p += len[i];
}
}
signed main() {
cin>>n>>m; For(i,1,n) cin>>a[i], len[i] = 1;
rt = bld();
while( m-- ) {
if( ind >= M ) rbld();
// dbg();
}
n = 0, dfs(rt); For(i,1,n) For(j,1,len[i]) cout<<a[i]<<" ";
}
-
KDT
-
LCT
#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
struct {
struct Node { int fa,ch[2]; bool rev; } t[];
void rev(int u) { swap(ls(u),rs(u)), t[u].rev ^= 1; }
void down(int u) { if( t[u].rev ) rev(ls(u)), rev(rs(u)), t[u].rev = 0; }
bool nrt(int u) { return ls(t[u].fa)==u || rs(t[u].fa)==u; }
bool wh(int u) { return rs(t[u].fa)==u; }
void rotate(int x) {
int y = t[x].fa, z = t[y].fa, k = wh(x), w = t[x].ch[!k];
if( nrt(y) ) t[z].ch[wh(y)] = x; t[x].ch[!k] = y, t[y].ch[k] = w;
t[w].fa = y, t[y].fa = x, t[x].fa = z;
}
void splay(int u) {
static int tp,stk[N];
for(int v = stk[tp=1] = u; nrt(v); stk[++tp] = v = t[v].fa);
while( tp ) down(stk[tp--]);
for(int fa; fa = t[u].fa, nrt(u); rotate(u))
if( nrt(fa) ) rotate(wh(fa)==wh(u)?fa:u);
}
void access(int x) {
for(int u = x, v = 0; u; u = t[v=u].fa) splay(u), rs(u) = v;
splay(x);
}
void mkrt(int u) { access(u), rev(u); }
int fdrt(int u) {
access(u);
while( ls(u) ) down(u), u = ls(u);
return splay(u), u;
}
void split(int u,int v) { mkrt(u), access(v); }
void link(int u,int v) { mkrt(u), t[u].fa = v; }
void cut(int u,int v) { split(u,v), t[u].fa = ls(v) = 0; }
} ;
- 珂朵莉樹
struct CT {
int l,r;
mutable int val;
CT(int l=0,int r=0,int val=0):l(l),r(r),val(val){}
bool operator < (const CT &rhs) const { return l < rhs.l; }
}; set<CT> ct;
auto split(int p) {
auto it = --ct.upper_bound({p});
if( it->l == p ) return it;
int l = it->l, r = it->r, x = it->val;
ct.erase(it), ct.emplace(l,p-1,x);
return ct.emplace(p,r,x).fi;
}
void assign(int l,int r,int x) {
auto itr = split(r+1), itl = split(l);
// if( itr != ct.end() && x == itr->val ) r = (itr++)->r;
// if( itl != ct.begin() && x == prev(itl)->val) l = (--itl)->l;
ct.erase(itl,itr), ct.emplace(l,r,x);
}
- 壓位 trie
值域 \([0,2^{20})\)
// bzoj3685 普通van Emde Boas樹
#define ctz(x) (uLL)__builtin_ctzll(x)
#define clz(x) (uLL)__builtin_clzll(x)
struct Trie {
uLL *t[4];
Trie() {
t[0] = new uLL[1<<14](), t[1] = new uLL[1<<8](),
t[2] = new uLL[1<<2](), t[3] = new uLL[1<<0]();
}
void ins(int x) {
Rep(i,0,4) {
uLL &u = t[i][x>>(i+1)*6], e = 1ull<<(x>>i*6&63);
if( u & e ) return; u |= e;
}
}
void ers(int x)
{ Rep(i,0,4) if( t[i][x>>(i+1)*6] &= ~(1ull<<(x>>i*6&63)) ) return; }
int min() {
if( !t[3][0] ) return -1;
int u = 0; rFor(i,3,0) u |= ctz(t[i][u>>(i+1)*6]) << i*6;
return u;
}
int max() {
if( !t[3][0] ) return -1;
int u = 0; rFor(i,3,0) u |= 63-clz(t[i][u>>(i+1)*6]) << i*6;
return u;
}
int suf(int x) {
Rep(i,0,4) {
int e = x>>i*6&63; uLL u = t[i][x>>(i+1)*6];
if( u>>e > 1 ) {
int res = x >> (i+1)*6 << (i+1)*6;
res |= ctz(u>>e+1)+e+1 << i*6;
rFor(j,i-1,0) res |= ctz(t[j][res>>(j+1)*6]) << j*6;
return res;
}
}
return -1;
}
int pre(int x) {
Rep(i,0,4) {
int e = x>>i*6&63; uLL u = t[i][x>>(i+1)*6];
if( u & (1ull<<e)-1 ) {
int res = x >> (i+1)*6 << (i+1)*6;
res |= 63-clz(u&(1ull<<e)-1) << i*6;
rFor(j,i-1,0) res |= 63-clz(t[j][res>>(j+1)*6]) << j*6;
return res;
}
}
return -1;
}
int qry(int x) { return t[0][x>>6] & 1ull<<(x&63) ? 1 : -1; }
} ;
塊狀
- 塊狀連結串列,值域分塊
值域同序列長度
// LG4278 帶插入區間K小值
const int N = 7e4+5, B = 512, BN = N/B+5;
struct DS { // 值域分塊
int sum[BN],cnt[N];
void add(int x,int y) { sum[x/B] += y, cnt[x] += y; }
};
struct Blk : Vi {
DS ds;
void ins(int i,int x) { emplace(begin()+i,x), ds.add(x,1); }
}; vector<Blk> bk(1); // 塊狀連結串列
Pii find(int p) { // 塊狀連結串列定位 p 位置
Rep(i,0,sz(bk))
if( p < sz(bk[i]) ) return {i,p};
else p -= sz(bk[i]);
return {sz(bk)-1,sz(bk.back())};
}
void ins(int p,int x) { // p 位置前插入 x
int i,j; tie(i,j) = find(p);
bk[i].ins(j,x);
Rep(k,i+1,sz(bk)) bk[k].ds.add(x,1);
if( sz(bk[i]) > 2*B ) {
Vi a(bk[i].end()-B,bk[i].end());
bk[i].erase(bk[i].end()-B,bk[i].end()),
bk.emplace(bk.begin()+i+1,Blk()), bk[i+1].ds = bk[i].ds;
for(int k : a) bk[i].ds.add(k,-1), bk[i+1].pb(k);
}
}
void mdf(int p,int x) { // p 位置的值改為 x
int i,j; tie(i,j) = find(p);
int y = bk[i][j]; bk[i][j] = x;
Rep(k,i,sz(bk)) bk[k].ds.add(x,1), bk[k].ds.add(y,-1);
}
int qry(int l,int r,int x) { // 查詢 [l,r] 第 x 小
static DS ds;
int li,lj,ri,rj; tie(li,lj) = find(l), tie(ri,rj) = find(r);
auto add=[&](int y) {
if( li == ri ) For(i,lj,rj) ds.add(bk[li][i],y);
else {
Rep(i,lj,sz(bk[li])) ds.add(bk[li][i],y);
For(i,0,rj) ds.add(bk[ri][i],y);
}
};
add(1);
for(int i = 0; ; ++i) {
int y = ds.sum[i] + (li<ri?bk[ri-1].ds.sum[i]-bk[li].ds.sum[i]:0);
if( x > y ) x -= y;
else {
i = i*B-1;
do
++i,
x -= ds.cnt[i] + (li<ri?bk[ri-1].ds.cnt[i]-bk[li].ds.cnt[i]:0);
while( x > 0 );
add(-1);
return i;
}
}
}