可持久化[学习笔记]
可持久化应该都知道…
就是可以回退历史版本…以及区间查询一些东西比如说k值…(不过k值还不是主要用处?)
可持久化略解:
就是复制其他的根节点 按照过去版本添加当前版本新建节点…和之前是独立的
但是是共用节点…从而使内存减少了很多…
按照以前的版本新建节点到当前的版本…复制版本就是直接复制根节点
rt[i]=rt[pre];
可持久化线段树
求静态区间k大…
就是弄个前缀和的东西 l~mid mid+1~r的这段值域中二分没了…
#include <cstdio>
#include <algorithm>
using ll = long long ;
using namespace std ;
int read() {
int x = 0 , f = 1 ; char c = getchar() ;
while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }
while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c & 15) ; c = getchar() ; }
return x * f ;
}
template < class T > void print(T x , char c = '\n') {
static char _st[100] ; int _stp = 0 ;
if(x == 0) { putchar('0') ; }
if(x < 0) { putchar('-') ; x = -x ; }
while(x) { _st[++ _stp] = (x % 10) ^ 48 ; x /= 10 ; }
while(_stp) { putchar(_st[_stp --]) ; }
putchar(c) ;
}
const int N = 2e5 + 10;
int n , m , a[N] , b[N] , rt[N] , ls[N << 5] , rs[N << 5] , sum[N << 5] , cnt = 0 ;
void upd(int pre , int & p , int l , int r , int val) {
ls[p = ++ cnt] = ls[pre] ; rs[p] = rs[pre] ;
sum[p] = sum[pre] + 1 ;
if(l == r) { return ; }
int mid = l + r >> 1 ;
if(val <= mid) { upd(ls[pre] , ls[p] , l , mid , val) ; }
else { upd(rs[pre] , rs[p] , mid + 1 , r , val) ; }
}
int query(int L , int R , int l , int r , int k) {
if(l == r) { return l ; }
int mid = l + r >> 1 , val = sum[ls[R]] - sum[ls[L]] ;
if(val >= k) { return query(ls[L] , ls[R] , l , mid , k) ; }
else { return query(rs[L] , rs[R] , mid + 1 , r , k - val) ; }
}
int main() {
n = read() ; m = read() ;
for(int i = 1 ; i <= n ; i ++) { a[i] = read() ; b[i] = a[i] ; }
sort(b + 1 , b + n + 1) ; int len = unique(b + 1 , b + n + 1) - b - 1 ;
for(int i = 1 ; i <= n ; i ++) { a[i] = lower_bound(b + 1 , b + len + 1 , a[i]) - b ; }
for(int i = 1 ; i <= n ; i ++) { upd(rt[i - 1] , rt[i] , 1 , n , a[i]) ; }
for(int i = 1 ; i <= m ; i ++) {
int l = read() , r = read() , k = read() ;
print(b[query(rt[-- l] , rt[r] , 1 , n , k)]) ;
}
return 0 ;
}
可持久化并查集
像是启发式合并一样 深度浅的弄到深度深的…
#include <cstdio>
using ll = long long ;
using namespace std ;
int read() {
int x = 0 , f = 1 ; char c = getchar() ;
while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }
while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c & 15) ; c = getchar() ; }
return x * f ;
}
template < class T > void print(T x , char c = '\n') {
static char _st[100] ; int _stp = 0 ;
if(x == 0) { putchar('0') ; }
if(x < 0) { putchar('-') ; x = -x ; }
while(x) { _st[++ _stp] = (x % 10) ^ 48 ; x /= 10 ; }
while(_stp) { putchar(_st[_stp --]) ; }
putchar(c) ;
}
const int N = 2e5 + 10 ;
int n , m , fa[N << 5] , dep[N << 5] ;
int ls[N << 5] , rs[N << 5] , rt[N] , cnt = 0 ;
void swap(int & x , int & y) { x ^= y ^= x ^= y ; }
void build(int & p , int l , int r) {
p = ++ cnt ;
if(l == r) { fa[p] = l ; return ; }
int mid = l + r >> 1 ;
build(ls[p] , l , mid) ; build(rs[p] , mid + 1 , r) ;
}
void upd(int pre , int & p , int l , int r , int pos , int f) {
p = ++ cnt ;
ls[p] = ls[pre] ; rs[p] = rs[pre] ;
if(l == r) { fa[p] = f ; dep[p] = dep[pre] ; return ; }
int mid = l + r >> 1 ;
if(pos <= mid) upd(ls[pre] , ls[p] , l , mid , pos , f) ;
else upd(rs[pre] , rs[p] , mid + 1 , r , pos , f) ;
}
int query(int p , int l , int r , int pos) {
if(l == r) { return p ; }
int mid = l + r >> 1 ;
if(pos <= mid) return query(ls[p] , l , mid , pos) ;
else return query(rs[p] , mid + 1 , r , pos) ;
}
void add(int p , int l , int r , int pos) {
if(l == r) { dep[p] ++ ; return ; }
int mid = l + r >> 1;
if(pos <= mid) add(ls[p] , l , mid , pos) ;
else add(rs[p] , mid + 1 , r , pos) ;
}
int find(int p , int x) {
int f = query(p , 1 , n , x) ;
if(x == fa[f]) { return f ; }
return find(p , fa[f]) ;
}
int main() {
n = read() ; m = read() ;
build(rt[0] , 1 , n) ;
for(int i = 1 ; i <= m ; i ++) {
int opt = read() ;
if(opt == 1) {
rt[i] = rt[i - 1] ;
int a = read() , b = read() ;
int f1 = find(rt[i] , a) , f2 = find(rt[i] , b) ;
if(fa[f1] == fa[f2]) { continue ; }
if(dep[f1] > dep[f2]) { swap(f1 , f2) ; }
upd(rt[i - 1] , rt[i] , 1 , n , fa[f1] , fa[f2]) ;
if(dep[f1] == dep[f2]) { add(rt[i] , 1 , n , fa[f2]) ; }
}
if(opt == 2) rt[i] = rt[read()] ;
if(opt == 3) {
rt[i] = rt[i - 1] ;
int a = read() , b = read() ;
int f1 = find(rt[i] , a) , f2 = find(rt[i] , b) ;
print(fa[f1] == fa[f2]) ;
}
}
return 0 ;
}
可持久化数组…
带修…回退查询
用可持久化线段树搞搞就好了…
// luogu-judger-enable-o2
//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
const int N = 1000000 + 5 ;
int n , q , a[N] , rt[N<<5] ;
struct node {
int lc[N<<5] , rc[N<<5] , val[N<<5] , cnt = 0 ;
inline void build(int l , int r , int &p) {
p = ++ cnt ;
if(l == r) {
val[p] = a[l] ;
return ;
}
int mid = l + r >> 1 ;
build(l , mid , lc[p]) ;
build(mid + 1 , r , rc[p]) ;
}
inline void Insert(int pre , int l , int r , int pos , int v , int & p) {
p = ++ cnt ;
lc[p]=lc[pre];
rc[p]=rc[pre];
val[p]=val[pre];
if(l == r) {
val[p] = v ;
return ;
}
int mid = l + r >> 1 ;
if(pos<=mid) Insert(lc[pre] , l , mid , pos , v , lc[p]) ;
else Insert(rc[pre] , mid + 1 , r , pos , v , rc[p]) ;
}
inline int Query(int l , int r , int p , int pos) {
if(l == r) return val[p] ;
int mid = l + r >> 1 ;
if(pos <= mid) return Query(l , mid , lc[p] , pos) ;
else return Query(mid + 1 , r , rc[p] , pos) ;
}
}T ;
signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() ; q = read() ;
for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
T.build(1,n,rt[0]) ;
for(register int i = 1 ; i <= q ; i ++) {
int pre (read()) ;
int opt (read()) ;
int x (read()) ;
if(opt == 1) {
int v = read() ;
T.Insert(rt[pre] , 1 , n , x , v , rt[i]) ;
}
else {
printf("%d\n" , T.Query(1 , n , rt[pre] , x)) ;
rt[i]=rt[pre] ;
}
}
return 0 ;
}
可持久化平衡树
平衡树的加强版(?)
但不能splay了…然后硬着头皮去学了fhq treap(fhq真香)
#include <cstdio>
#include <bits/stdc++.h>
using ll = long long ;
using namespace std ;
int read() {
int x = 0 , f = 1 ; char c = getchar() ;
while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }
while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c & 15) ; c = getchar() ; }
return x * f ;
}
template < class T > void print(T x , char c = '\n') {
static char _st[100] ; int _stp = 0 ;
if(x == 0) { putchar('0') ; }
if(x < 0) { putchar('-') ; x = -x ; }
while(x) { _st[++ _stp] = (x % 10) ^ 48 ; x /= 10 ; }
while(_stp) { putchar(_st[_stp --]) ; }
putchar(c) ;
}
const int N = 1e6 + 10 ;
struct Node {
int val , sz , rnd , ch[2] ;
} tr[N * 80] ;
int n , cnt = 0 , rt[N] ;
#define ls(x) tr[x].ch[0]
#define rs(x) tr[x].ch[1]
void pushup(int x) { tr[x].sz = tr[ls(x)].sz + tr[rs(x)].sz + 1 ; }
int merge(int u , int v) {
if(! u || ! v) return u | v ;
int p = ++ cnt ;
if(tr[u].rnd < tr[v].rnd) {
tr[p] = tr[u] ; rs(p) = merge(rs(p) , v) ;
pushup(p) ; return p ;
}
else {
tr[p] = tr[v] ; ls(p) = merge(u , ls(p)) ;
pushup(p) ; return p ;
}
}
void split(int x , int k , int & u , int & v) {
if(! x) { u = v = 0 ; return ; }
if(k >= tr[x].val) { tr[u = ++ cnt] = tr[x] ; split(rs(u) , k , rs(u) , v) ; pushup(u) ; }
else { tr[v = ++ cnt] = tr[x] ; split(ls(v) , k , u , ls(v)) ; pushup(v) ; }
}
int main() {
auto insert = [&] (int & rt , int val) {
auto Newnode = [&] (int val){
tr[++ cnt] = { val , 1 , rand() } ;
return cnt ;
} ;
int x, y ;
split(rt , val , x , y) ;
rt = merge(merge(x , Newnode(val)) , y) ;
} ;
auto remove = [&] (int & rt , int val) {
int x , y , z ;
split(rt , val , x , z) ; split(x , val - 1 , x , y) ;
rt = merge(merge(x , merge(ls(y) , rs(y))) , z) ;
} ;
auto rank = [&] (int & rt , int val) {
int x , y ;
split(rt , val - 1 , x , y) ;
int ans = tr[x].sz + 1 ;
rt = merge(x , y) ;
return ans ;
} ;
auto kth = [&] (int rt , int k) {
while(rt) {
int sum = tr[ls(rt)].sz + 1 ;
if(sum == k) { return tr[rt].val ; }
if(sum > k) { rt = ls(rt) ; }
else { k -= sum ; rt = rs(rt) ; }
}
} ;
auto pre = [&] (int rt , int v) {
int ans = -2147483647 ;
while(rt) {
if(tr[rt].val < v) { ans = tr[rt].val ; rt = rs(rt) ; }
else { rt = ls(rt) ; }
}
return ans ;
} ;
auto nxt = [&] (int rt , int v) {
int ans = 2147483647 ;
while(rt) {
if(tr[rt].val > v) { ans = tr[rt].val ; rt = ls(rt) ; }
else { rt = rs(rt) ; }
}
return ans ;
} ;
n = read() ;
for(int i = 1 ; i <= n ; i ++) {
int ver = read() , opt = read() , x = read() ;
rt[i] = rt[ver] ;
if(opt == 1) insert(rt[i] , x) ;
if(opt == 2) remove(rt[i] , x) ;
if(opt == 3) print(rank(rt[i] , x)) ;
if(opt == 4) print(kth(rt[i] , x)) ;
if(opt == 5) print(pre(rt[i] , x)) ;
if(opt == 6) print(nxt(rt[i] , x)) ;
}
return 0 ;
}
可持久化文艺平衡树
区间翻转…回退历史版本
还是可持久化平衡树… 支持插入…
#include <cstdio>
#include <bits/stdc++.h>
using ll = long long ;
using namespace std ;
int read() {
int x = 0 , f = 1 ; char c = getchar() ;
while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }
while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c & 15) ; c = getchar() ; }
return x * f ;
}
template < class T > void print(T x , char c = '\n') {
static char _st[100] ; int _stp = 0 ;
if(x == 0) { putchar('0') ; }
if(x < 0) { putchar('-') ; x = -x ; }
while(x) { _st[++ _stp] = (x % 10) ^ 48 ; x /= 10 ; }
while(_stp) { putchar(_st[_stp --]) ; }
putchar(c) ;
}
int n ; ll lastans = 0 ;
const int N = 2e5 + 10 ;
int rt[N] ;
struct Node {
int ls , rs , val , rnd , sz ;
ll sum ; bool rev ;
} tr[N * 80] ;
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
int cnt = 0 ;
void pushup(int x) { tr[x].sz = tr[ls(x)].sz + tr[rs(x)].sz + 1 ; tr[x].sum = tr[ls(x)].sum + tr[rs(x)].sum + tr[x].val ; }
void pushdown(int x) {
if(! tr[x].rev) return ;
if(ls(x)) { int tmp = ls(x) ; tr[tr[x].ls = ++ cnt] = tr[tmp] ; tr[ls(x)].rev = tr[tmp].rev ^ 1 ; }
if(rs(x)) { int tmp = rs(x) ; tr[tr[x].rs = ++ cnt] = tr[tmp] ; tr[rs(x)].rev = tr[tmp].rev ^ 1 ; }
swap(tr[x].ls , tr[x].rs) ; tr[x].rev = 0 ;
}
int NewNode(int v) { tr[++ cnt] = { 0 , 0 , v , rand() , 1 , v , 0 } ; return cnt ; }
int Merge(int u , int v) {
if(! u || ! v) return u | v ;
if(tr[u].rnd < tr[v].rnd) { pushdown(u) ; rs(u) = Merge(rs(u) , v) ; pushup(u) ; return u ; }
pushdown(v) ; ls(v) = Merge(u , ls(v)) ; pushup(v) ; return v ;
}
void Split(int cur , int k , int & u , int & v) {
if(! cur) { u = v = 0 ; return ; }
pushdown(cur) ;
if(k > tr[ls(cur)].sz) { tr[u = ++ cnt] = tr[cur] ; Split(rs(cur) , k - tr[ls(cur)].sz - 1 , rs(u) , v) ; pushup(u) ; }
else { tr[v = ++ cnt] = tr[cur] ; Split(ls(cur) , k , u , ls(v)) ; pushup(v) ; }
}
void Insert(int & rt , int p , int val) {
int x , y ; Split(rt , p , x , y) ;
rt = Merge(Merge(x , NewNode(val)) , y) ;
}
void Remove(int & rt , int p) {
int x , y , z ; Split(rt , p , x , z) ; Split(x , p - 1 , x , y) ;
rt = Merge(x , z) ;
}
void Reverse(int & rt , int l , int r) {
int x , y , z ; Split(rt , r , x , z) ; Split(x , l - 1 , x , y) ;
tr[y].rev ^= 1 ; rt = Merge(x , Merge(y , z)) ;
}
ll Query(int & rt , int l , int r) {
int x , y , z ; Split(rt , r , x , z) ; Split(x , l - 1 , x , y) ;
ll ans = tr[y].sum ; rt = Merge(x , Merge(y , z)) ; return ans ;
}
int main() {
srand(19260817) ;
n = read() ;
for(int i = 1 ; i <= n ; i ++) {
int ver = read() , opt = read() ; ll x = read() ^ lastans , y ;
rt[i] = rt[ver] ;
if(opt != 2) { y = read() ^ lastans ; }
if(opt == 1) { Insert(rt[i] , x , y) ; }
if(opt == 2) { Remove(rt[i] , x) ; }
if(opt == 3) { Reverse(rt[i] , x , y) ; }
if(opt == 4) { print(lastans = Query(rt[i] , x , y)) ; }
}
return 0 ;
}
可持久化trie树的话就…
int tot = 0 ;
int t[N] ; int ch[N << 5][2] ;
int sz[N << 5] ;
inline void upd(int x , int p , int q) {
ch[p][0] = ch[q][0] ; ch[p][1] = ch[q][1] ; sz[p] = sz[q] + 1 ;
for(register int i = 29 ; ~ i ; i --) {
int c = (x >> i) & 1 ;
ch[p][c] = ++ tot ;
p = ch[p][c] ;
q = ch[q][c] ;
ch[p][0] = ch[q][0] ;
ch[p][1] = ch[q][1] ;
sz[p] = sz[q] + 1 ;
}
}
inline int query(int x , int p , int q) {
int res = 0 ;
for(register int i = 29 ; ~ i ; i --) {
int c = (x >> i) & 1 ;
if(sz[ch[q][c ^ 1]] - sz[ch[p][c ^ 1]]) res |= 1 << i , p = ch[p][c ^ 1] , q = ch[q][c ^ 1] ;
else p = ch[p][c] , q = ch[q][c] ;
} return res ;
}
可持久化的题目…
高级打字机
#include<bits/stdc++.h>
using namespace std ;
int n ;
const int N = 1e5 + 10 ;
int rt[N] , cnt[N] ;
int ls[N << 5] , rs[N << 5] ;
char val[N << 5] ;
int tot = 0 , num = 0 ;
inline void build(int l , int r , int & o) {
o = ++ tot ;
if(l == r) { return ; }
int mid = l + r >> 1 ;
build(l , mid , ls[o]) ;
build(mid + 1 , r , rs[o]) ;
}
inline void upd(int x , int l , int r , int pre , int & o , char c) {
ls[o = ++ tot] = ls[pre] ;
rs[o] = rs[pre] ;
if(l == r) { val[o] = c ; return ; }
int mid = l + r >> 1 ;
if(x <= mid) upd(x , l , mid , ls[pre] , ls[o] , c) ;
else upd(x , mid + 1 , r , rs[pre] , rs[o] , c) ;
}
inline char query(int x , int l , int r , int o) {
if(l == r) return val[o] ;
int mid = l + r >> 1 ;
if(x <= mid) return query(x , l , mid , ls[o]) ;
else return query(x , mid + 1 , r , rs[o]) ;
}
signed main() {
#ifdef _WIN64
freopen("0.in" , "r" , stdin) ;
#endif
ios :: sync_with_stdio(false) ;
cin.tie(nullptr) ; cout.tie(nullptr) ;
cin >> n ;
build(1 , n , rt[0]) ;
for(register int i = 1 ; i <= n ; i ++) {
char opt ; cin >> opt ;
if(opt == 'T') { char c ; cin >> c ; ++ num ; upd(cnt[num] = cnt[num - 1] + 1 , 1 , n , rt[num - 1] , rt[num] , c) ; }
if(opt == 'U') { int x ; cin >> x ; ++ num ; cnt[num] = cnt[num - x - 1] ; rt[num] = rt[num - x - 1] ; }
if(opt == 'Q') { int x ; cin >> x ; cout << query(x , 1 , n , rt[num]) << '\n' ; }
}
return 0 ;
}
每次记下LCA 和 FA[LCA]就可以了吧
// luogu-judger-enable-o2
//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
const int N = 1e5 + 10 ;
const int M = N << 5 ;
int n , q ; int m ;
int sum[M] , L[M] , R[M] ;
int a[N] , b[N] , rt[N] ;
struct node{
int v ;
int nxt ;
};
node e[N << 1] ;
int head[N] ;
int fa[N] , size[N] , d[N] , son[N] , top[N] ;
int cnt = 0 ;
inline void Add(int u , int v) {
e[ ++ cnt] . v = v ;
e[ cnt] . nxt = head[u] ;
head[u] = cnt ;
return ;
}
int tot = 0 ;
inline void Update(int last , int & now , int l , int r , int x) {
sum[now = ++ tot] = sum[last] + 1 ;
if(l == r) return ;
int mid = l + r >> 1 ;
if(x <= mid) R[now] = R[last] , Update(L[last] , L[now] , l , mid , x) ;
else L[now] = L[last] , Update(R[last] , R[now] , mid + 1 , r , x) ;
return ;
}
inline int Query(int a , int b , int lca ,int lca_fa , int l , int r , int k) {
if(l >= r) return l ;
int x = sum[L[a]] + sum[L[b]] - sum[L[lca]] - sum[L[lca_fa]] ;
int mid = l + r >> 1 ;
if(x >= k) return Query(L[a] , L[b] , L[lca] , L[lca_fa] , l , mid , k) ;
else return Query(R[a] , R[b] , R[lca] , R[lca_fa] , mid + 1 , r , k - x) ;
}
inline void Dfs(int u) {
size[u] = 1 ;
Update(rt[fa[u]] , rt[u] , 1 , m , a[u]) ;
for(register int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if(v == fa[u]) continue ;
fa[v] = u ;
d[v] = d[u] + 1 ;
Dfs(v) ;
size[u] += size[v] ;
if(size[v] > size[son[u]]) son[u] = v ;
}
}
inline void Dfs2(int u , int t) {
top[u] = t ;
if(! son[u]) return ;
Dfs2(son[u] , t) ;
for(register int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if(v ^ fa[u] && v ^ son[u]) Dfs2(v , v) ;
}
}
inline int Lca(int x , int y) {
int fx = top[x] ;
int fy = top[y] ;
while(fx ^ fy) {
if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
x = fa[fx] ;
fx = top[x] ;
}
if(d[x] > d[y]) swap(x , y) ;
return x ;
}
signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() , q = read() ;
for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
for(register int i = 1 ; i <= n ; i ++) b[i] = a[i] ;
sort(b + 1 , b + n + 1) ;
m = unique(b + 1 , b + 1 + n) - b - 1 ;
for(register int i = 1 ; i <= n ; i ++)
a[i] = lower_bound(b + 1 , b + m + 1 , a[i]) - b ;
for(register int i = 1 ; i <= n - 1 ; i ++) {
int u = read() , v = read() ;
Add(u , v) ;
Add(v , u) ;
}
Dfs(1) ;
Dfs2(1 , 1) ;
int ans = 0 ;
for(register int i = 1 ; i <= q ; i ++) {
int x = read() ^ ans , y = read() ;
int lca = Lca(x , y) ;
int z = read() ;
write(ans = b[Query(rt[x] , rt[y] , rt[lca] , rt[fa[lca]] , 1 , m , z)]) ;
}
return 0 ;
}
// luogu-judger-enable-o2
//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
const int N = 5e5 + 5 ;
struct node {
int l , r , sum ;
};
int a[N] ;
node T[N << 5] ;
int n , m , root[N] , cnt = 1 ;
inline void Insert(int & p , int l , int r , int x) {
T[cnt ++] = T[p] ; p = cnt - 1 ;
T[p].sum ++ ;
if(l == r) return ;
int mid = l + r >> 1 ;
if(x <= mid) Insert(T[p].l , l , mid , x) ;
else Insert(T[p].r , mid + 1 , r , x) ;
}
inline int Query(int a , int b , int l , int r , int len) {
if(l == r) return l ;
int mid = l + r >> 1 ;
if(T[T[b].l].sum - T[T[a].l].sum << 1 > len) return Query(T[a].l , T[b].l , l , mid , len) ;
if(T[T[b].r].sum - T[T[a].r].sum << 1 > len) return Query(T[a].r , T[b].r , mid + 1 , r , len) ;
return 0 ;
}
signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() ; m = read() ;
for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
for(register int i = 1 ; i <= n ; i ++) Insert(root[i] = root[i - 1] , 1 , n , a[i]) ;
for(register int i = 1 ; i <= m ; i ++) {
int l = read() , r = read() ;
printf("%d\n" , Query(root[l - 1] , root[r] , 1 , n , r - l + 1)) ;
}
return 0 ;
}
一堆题
懒得写解法自己看呗…
[CQOI2015]任务查询系统
// luogu-judger-enable-o2
// Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline void Open() {
ios::sync_with_stdio(0) ;
cin.tie(0) ;
cout.tie(0) ;
}
int n , q ;
const int N = 2e5 + 5 ;
const int M = N << 5 ;
int ls[M] , rs[M] , num[M] , rt[N] , sp[N] ;
long long sum[M] ;
struct node {
int v ;
int nxt ;
};
int head[N] ;
node e[N << 1] ;
int cnt = 0 ;
inline void Add(int u , int v) {
e[++ cnt].v = v ;
e[cnt].nxt = head[u] ;
head[u] = cnt ;
return ;
}
inline int abs(int x){ return x>0?x:-x;}
inline int max(int x , int y) { return x > y ? x : y ;}
int tot = 0 ;
inline void Upd(int & p , int last , int l , int r , int x) {
if(! p) p = ++ tot ;
num[p] = num[last] + (x < 0 ? -1 : 1) ;
sum[p] = sum[last] + x ;
if(l == r) return ;
int mid = l + r >> 1 ;
if(abs(x) <= mid) {
rs[p] = rs[last] ;
Upd(ls[p] , ls[last] , l , mid , x) ;
}
else {
ls[p] = ls[last] ;
Upd(rs[p] , rs[last] , mid + 1 , r , x) ;
}
}
inline long long Query(int l , int r , int u , int k) {
if(l == r) return k * l ;
int mid = l + r >> 1 ;
if(k <= num[ls[u]]) return Query(l , mid , ls[u] , k) ;
else return Query(mid + 1 , r , rs[u] , k - num[ls[u]]) + sum[ls[u]] ;
}
signed main() {
Open() ;
cin >> n >> q ;
int maxn = -1e9 ;
for(register int i = 1 ; i <= n ; i ++) {
int u , v , e ;
cin >> u >> v >> e ;
Add(u , e) ;
Add(v + 1 , -e) ;
maxn = max(maxn , e) ;
}
int m = 0 ;
for(register int u = 1 ; u <= n ; u ++) {
for(register int i = head[u] ; i ; i = e[i].nxt) {
m ++ ;
Upd(rt[m] , rt[m - 1] , 1 , maxn , e[i].v) ;
}
sp[u] = m ;
}
long long ans = 1 ;
for(register int i = 1 ; i <= q ; i ++) {
int x , a , b , c ;
cin >> x >> a >> b >> c ;
long long k = (1LL * a * ans + b) % c + 1 ;
ans = (num[rt[sp[x]]] <= k) ? sum[rt[sp[x]]] : Query(1 , maxn , rt[sp[x]] , k) ;
cout << ans << endl ;
}
return 0 ;
}
// luogu-judger-enable-o2
#include<iostream>
using namespace std ;
int n , m ;
const int N = 5e5 + 5 ;
int a[N] ;
int cnt , t[N << 5] , ch[N << 5][2] , sum[N << 5] ;
inline void Upd(int pos , int pre , int l , int r , int & p) {
if(r < pos || l > pos) return ;
p = ++ cnt ;
ch[p][0] = ch[pre][0] ;
ch[p][1] = ch[pre][1] ;
sum[p] = sum[pre] + 1 ;
if(l == r) {
return ;
}
int mid = l + r >> 1 ;
Upd(pos , ch[pre][0] , l , mid , ch[p][0]) ;
Upd(pos , ch[pre][1] , mid + 1 , r , ch[p][1]) ;
}
inline int Query(int u , int v , int a , int b , int l , int r) {
int num = sum[v] - sum[u] , mid = l + r >> 1 ;
if(b < l || a > r || ! num) return 0 ;
if(a <= l && r <= b) return num ;
return Query(ch[u][0] , ch[v][0] , a , b , l , mid) + Query(ch[u][1] , ch[v][1] , a , b , mid + 1 , r) ;
}
inline int max(register int x , register int y) {
return x > y ? x : y ;
}
signed main() {
ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0) ;
cin >> n >> m ;
int mx = -1e9 ;
for(register int i = 1 ; i <= n ; i ++) cin >> a[i] ;
for(register int i = 1 ; i <= n ; i ++) mx = max(a[i] , mx) ;
for(register int i = 1 ; i <= n ; i ++) {
Upd(a[i] , t[i - 1] , 0 , mx , t[i]) ;
}
for( ; m -- ; ) {
register int b , x , l , r ;
cin >> b >> x >> l >> r ;
int ans = 0 ;
for(register int i = 18 ; i >= 0 ; i --) {
if(b & (1 << i) && ! Query(t[l - 1] , t[r] , ans - x , ans - x + (1 << i) - 1 , 0 , mx)) ans += 1 << i ;
if(! (b & (1 << i)) && Query(t[l - 1] , t[r] , ans - x + (1 << i) , ans - x + (1 << i + 1) - 1 , 0 , mx)) ans += 1 << i ;
}
cout << (ans ^ b) << endl ;
}
return 0 ;
}
这题提供三种做法…
#include<bits/stdc++.h>
using namespace std ;
inline int min(int x , int y) { return x < y ? x : y ; }
int n , m ;
const int N = 1e6 + 10 ;
int a[N] , mn[N << 2] ;
typedef pair < int , int > pii ;
vector < pii > vr[N] ;
inline void update(int x , int l , int r , int rt , int val) {
if(l == r) { mn[rt] = val ; return ; }
int mid = l + r >> 1 ;
if(x <= mid) update(x , l , mid , rt << 1 , val) ;
else update(x , mid + 1 , r , rt << 1 | 1 , val) ;
mn[rt] = min(mn[rt << 1] , mn[rt << 1 | 1]) ;
}
inline int query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) { return mn[rt] ; }
int mid = l + r >> 1 , ans = INT_MAX ;
if(a <= mid) ans = min(ans , query(a , b , l , mid , rt << 1)) ;
if(b > mid) ans = min(ans , query(a , b , mid + 1 , r , rt << 1 | 1)) ;
return ans ;
}
struct pri_que {
priority_queue < int , vector < int > , greater < int > > a , b ;
inline void push(int x) { a.push(x) ; }
inline void pop(int x) { b.push(x) ; }
inline int top() { while(a.top() == b.top()) { a.pop() ; b.pop() ; } return a.top() ; }
} q ;
int las[N] , ans[N] ;
bool vis[N] ;
signed main() {
#ifdef _WIN64
freopen("a.in" , "r" , stdin) ;
#endif
ios :: sync_with_stdio(false) ; cin.tie(nullptr) ; cout.tie(nullptr) ;
cin >> n >> m ;
for(register int i = 1 ; i <= n ; i ++) cin >> a[i] ;
for(register int i = 1 ; i <= m ; i ++) { int l , r ; cin >> l >> r ; vr[r].push_back(pii(l , i)) ; }
for(register int i = 0 ; i <= 1e6 ; i ++) q.push(i) ;
for(register int i = 1 ; i <= n ; i ++) {
if(! vis[a[i]]) vis[a[i]] = 1 , q.pop(a[i]) ;
if(las[a[i]]) update(las[a[i]] , 1 , n , 1 , INT_MAX) ;
las[a[i]] = i ; update(i , 1 , n , 1 , a[i]) ;
for( pii x : vr[i] ) {
ans[x.second] = q.top() ;
if(x.first > 1) { ans[x.second] = min(ans[x.second] , query(1 , x.first - 1 , 1 , n , 1)) ; }
}
}
for(register int i = 1 ; i <= m ; i ++) cout << ans[i] << '\n' ;
return 0 ;
}
// luogu-judger-enable-o2
//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
if(x == 0) return (void) puts("0") ;
if(x < 0) putchar('-') , x = -x ;
for( ; x ; x /= 10) st[++ tp] = x % 10 ;
for( ; tp ; tp --) putchar(st[tp] + '0') ;
putchar(c) ;
}
//#define Online_Judge
int n , m ;
const int N = 200000 + 5 ;
int a[N] ;
int vis[N + 10] ;
struct node {
int l , r ;
int id ;
};
node q[N] ;
int unt ;
int ans = 0 ;
int Answer[N] ;
inline bool cmp(node x , node y) {
if(x.l / unt ^ y.l / unt) return x.l < y.l ;
if(x.r ^ y.r) return x.r < y.r ;
return x.id < y.id ;
}
inline void Ins(int x) {
if(x > N) return ;
vis[x] ++ ;
if(vis[x] > 1) return ;
if(x == ans) {
while(vis[ans]) ans ++ ;
return ;
}
}
inline void Del(int x) {
if(x > N) return ;
vis[x] -- ;
if(vis[x] == 0) ans = min(ans , x) ;
}
signed main() {
#ifdef Online_Judge
freopen("testdata.in" , "r" , stdin) ;
freopen("testdata2.out" , "w" , stdout) ;
#endif
n = read() , m = read() ; unt = sqrt(n) ;
for(register int i = 1 ; i <= n ; i ++) a[i] = read() ;
for(register int i = 1 ; i <= m ; i ++) {
int l = read() , r = read() ;
q[i] = {l , r , i} ;
}
sort(q + 1 , q + m + 1 , cmp) ;
int l = 1 , r = 0 ;
for(register int i = 1 ; i <= m ; i ++) {
for( ; l < q[i].l ; Del(a[l ++])) ;
for( ; l > q[i].l ; Ins(a[-- l])) ;
for( ; r < q[i].r ; Ins(a[++ r])) ;
for( ; r > q[i].r ; Del(a[r --])) ;
Answer[q[i].id] = ans ;
}
for(register int i = 1 ; i <= m ; i ++) write(Answer[i]) ;
return 0 ;
}
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std ;
int n , q ;
const int N = 1e6 + 10 ;
int ls[N * 40] , rs[N * 40] , rt[N] , v[N * 40] ;
int cnt = 0 ;
inline int min(int x , int y) { return x < y ? x : y ; }
inline void build(int l , int r , int & o) {
o = ++ cnt ;
if(l == r) return ;
int mid = l + r >> 1 ;
build(l , mid , ls[o]) ;
build(mid + 1 , r , rs[o]) ;
}
inline void update(int l , int r , int pre , int & o , int val , int x) {
o = ++ cnt ; ls[o] = ls[pre] ; rs[o] = rs[pre] ;
if(l == r) { v[o] = x ; return ; }
int mid = l + r >> 1 ;
if(val <= mid) update(l , mid , ls[pre] , ls[o] , val , x) ;
else update(mid + 1 , r , rs[pre] , rs[o] , val , x) ;
v[o] = min(v[ls[o]] , v[rs[o]]) ;
}
int goal = 0 ;
inline int query(int l , int r , int o) {
if(l == r) return l ;
int mid = l + r >> 1 ;
if(v[ls[o]] < goal) return query(l , mid , ls[o]) ;
else return query(mid + 1 , r , rs[o]) ;
}
const int L = 0 , R = 1e6 + 1 ;
signed main() {
#ifdef _WIN64
freopen("a.in" , "r" , stdin) ;
#endif
ios :: sync_with_stdio(false) ;
cin.tie(nullptr) ;
cout.tie(nullptr) ;
cin >> n >> q ;
build(L , R , rt[0]) ;
for(register int i = 1 ; i <= n ; i ++) {
int x ; cin >> x ;
update(L , R , rt[i - 1] , rt[i] , x , i) ;
}
while(q --) {
int l , r ; cin >> l >> r ;
goal = l ; cout << query(L , R , rt[r]) << '\n' ;
}
return 0 ;
}
// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define rep(i , j , n) for(register int i=j;i<=n;i++)
#define Rep(i , j , n) for(register int i=j;i>=n;i--)
#define gc c = getchar()
inline int read() { register int x = 0 , f = 1 ; register char c ;
while(isspace(gc)) ; c == '-' ? f = -1 , gc : 0 ;
while((x *= 10) += (c ^ 48) , isdigit(gc)) ;
return x * f ;
}
using namespace std ;
const int N = 3000000 + 5 ;
int n , m , Sum ;
int l , r , x , k ;
int tree[N << 5][2] ;
int root[N << 5] ;
int sum[N << 5] ;
int d[40] ;
int cnt ;
inline void Split(int k) {
int l = 0 ;
while(k) {
d[++ l] = k & 1 ;
k >>= 1 ;
}
for(register int i=l+1;i<=27;i++) d[i] = 0 ;
}
inline void Build(int x , int & y) {
cnt ++ ; y = cnt ;
sum[y] = sum[x] + 1 ;
int now = y ;
for(register int i=27;i>=1;i--) {
tree[now][d[i]^1] = tree[x][d[i]^1] ;
cnt ++ ;
tree[now][d[i]] = cnt ;
now = cnt ;
x = tree[x][d[i]] ;
sum[now] = sum[x] + 1 ;
}
}
inline int Query(int x , int y) {
int ans = 0 ;
for(register int i=27;i>=1;i--) {
if(sum[tree[y][d[i]^1]] - sum[tree[x][d[i]^1]] > 0) {
ans += 1 << i - 1 ;
y = tree[y][d[i]^1] ;
x = tree[x][d[i]^1] ;
}
else {
y = tree[y][d[i]] ;
x = tree[x][d[i]] ;
}
}
return ans ;
}
signed main() {
// freopen("text.in" , "r" , stdin) ;
// freopen("text.out" , "w" , stdout) ;
n = read() , m = read() ;
cnt = 0 ; Split(0) ;
tree[0][0] = tree[0][1] = root[0] = 0 ;
Build(root[0] , root[1]) ;
n ++ ; Sum = 0 ;
for(register int i=2;i<=n;i++) {
x = read() ;
Sum ^= x ;
Split(Sum) ;
Build(root[i - 1] , root[i]) ;
}
char s[10] ;
for(register int i=1;i<=m;i++) {
scanf("%s" , s) ;
if(s[0] == 'A') {
n ++ ;
x = read() ;
Sum ^= x ;
Split(Sum) ;
Build(root[n - 1] , root[n]) ;
}
else {
l = read() , r = read() , k = read() ;
k ^= Sum ;
Split(k) ;
printf("%d\n" , Query(root[l - 1] , root[r])) ;
}
}
return 0 ;
}
之后咕咕咕咕。。有空再填坑…