训练计划Day2
Day2:线段树(可持久化),平衡树(splay,treap),并查集,树链剖分,动态树,树状数组,点分治(可持久)。
- 线段树模板
//区间最大,and,or
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline void read(int &x){
x=0;static char ch;static bool flag;flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);++i)
const int maxn = 100010;
const int bas = 0x7fffffff;
int T[maxn<<2],lazy[maxn<<2],sam[maxn<<2];
int a[maxn];
inline void update(int rt){
T[rt] = max(T[rt<<1],T[rt<<1|1]);
sam[rt] = (sam[rt<<1]&sam[rt<<1|1]) & (~(T[rt<<1]^T[rt<<1|1]));
}
inline void pushdown(int rt){
if(lazy[rt] == 0) return ;
T[rt<<1] += lazy[rt];lazy[rt<<1] += lazy[rt];
T[rt<<1|1] += lazy[rt];lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
void build(int rt,int l,int r){
if(l == r){
T[rt] = a[l];
sam[rt] = bas;
return ;
}int mid = l+r >> 1;
build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
update(rt);
}
int L,R,val,tmp;
inline bool check_a(int rt){
tmp = (val^bas);
return (tmp & sam[rt]) == tmp;
}
void modify_a(int rt,int l,int r){
if(L <= l && r <= R && check_a(rt)){
tmp = (T[rt] & val) - T[rt];
lazy[rt] += tmp;T[rt] += tmp;
return ;
}int mid = l+r >> 1;pushdown(rt);
if(L <= mid) modify_a(rt<<1,l,mid);
if(R > mid) modify_a(rt<<1|1,mid+1,r);
update(rt);
}
void modify_o(int rt,int l,int r){
if(L <= l && r <= R && (sam[rt] & val) == val){
tmp = (T[rt] | val) - T[rt];
lazy[rt] += tmp;T[rt] += tmp;
return ;
}int mid = l+r >> 1;pushdown(rt);
if(L <= mid) modify_o(rt<<1,l,mid);
if(R > mid) modify_o(rt<<1|1,mid+1,r);
update(rt);
}
int query(int rt,int l,int r){
if(L <= l && r <= R) return T[rt];
int mid = l+r >> 1;pushdown(rt);
if(R <= mid) return query(rt<<1,l,mid);
if(L > mid) return query(rt<<1|1,mid+1,r);
return max(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
}
int main(){
//freopen("series_wei.in","r",stdin);
//freopen("series_wei.out","w",stdout);
int n,m;read(n);read(m);
rep(i,1,n) read(a[i]);
build(1,1,n);int opt;
int cnt = 0 ;
while(m--){
read(opt);read(L);read(R);
if(opt == 1) read(val),modify_a(1,1,n);
else if(opt == 2) read(val),modify_o(1,1,n);
else printf("%d\n",query(1,1,n));
}
return 0;
}
//poj 3225 线段树成段替换与异或
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 131072;
bool hash[maxn];
int cover[maxn<<2];
int XOR[maxn<<2];
void FXOR(int rt) {
if (cover[rt] != -1) cover[rt] ^= 1;
else XOR[rt] ^= 1;
}
void PushDown(int rt) {
if (cover[rt] != -1) {
cover[rt<<1] = cover[rt<<1|1] = cover[rt];
XOR[rt<<1] = XOR[rt<<1|1] = 0;
cover[rt] = -1;
}
if (XOR[rt]) {
FXOR(rt<<1);
FXOR(rt<<1|1);
XOR[rt] = 0;
}
}
void update(char op,int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
if (op == 'U') {
cover[rt] = 1;
XOR[rt] = 0;
} else if (op == 'D') {
cover[rt] = 0;
XOR[rt] = 0;
} else if (op == 'C' || op == 'S') {
FXOR(rt);
}
return ;
}
PushDown(rt);
int m = (l + r) >> 1;
if (L <= m) update(op , L , R , lson);
else if (op == 'I' || op == 'C') {
XOR[rt<<1] = cover[rt<<1] = 0;
}
if (m < R) update(op , L , R , rson);
else if (op == 'I' || op == 'C') {
XOR[rt<<1|1] = cover[rt<<1|1] = 0;
}
}
void query(int l,int r,int rt) {
if (cover[rt] == 1) {
for (int it = l ; it <= r ; it ++) {
hash[it] = true;
}
return ;
} else if (cover[rt] == 0) return ;
if (l == r) return ;
PushDown(rt);
int m = (l + r) >> 1;
query(lson);
query(rson);
}
int main() {
cover[1] = XOR[1] = 0;
char op , l , r;
int a , b;
while ( ~scanf("%c %c%d,%d%c\n",&op , &l , &a , &b , &r) ) {
a <<= 1 , b <<= 1;
if (l == '(') a ++;
if (r == ')') b --;
if (a > b) {
if (op == 'C' || op == 'I') {
cover[1] = XOR[1] = 0;
}
} else update(op , a , b , 0 , maxn , 1);
}
query(0 , maxn , 1);
bool flag = false;
int s = -1 , e;
for (int i = 0 ; i <= maxn ; i ++) {
if (hash[i]) {
if (s == -1) s = i;
e = i;
} else {
if (s != -1) {
if (flag) printf(" ");
flag = true;
printf("%c%d,%d%c",s&1?'(':'[' , s>>1 , (e+1)>>1 , e&1?')':']');
s = -1;
}
}
}
if (!flag) printf("empty set");
puts("");
return 0;
}
//树状数组扫描线
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int Maxn=4005;
const int Maxp=1e5+5;
struct node{
int up,low,v;
};
struct node2{
int p,id;
};
int n,m,p,q;
int ans[Maxp],tr[4*Maxn];
vector<node> lne[Maxn];
vector<node2> ask[Maxn];
inline int lowbit(int x){
return x&(-x);
}
inline void read(int &x){
x=0; int f=1; char ch;
do{ch=getchar(); if(ch=='-') f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0'; ch=getchar();} while(ch>='0'&&ch<='9');
x*=f;
}
void add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i))
tr[i]+=v;
}
int srch(int x){
int sum=0;
for(int i=x;i;i-=lowbit(i))
sum+=tr[i];
return sum;
}
int main(){
read(n),read(m),read(p),read(q);
for(int i=1;i<=p;i++){
int a,b,c,d;
read(a),read(b),read(c),read(d);
node stp;
stp.up=a,stp.low=c,stp.v=1;
lne[b].push_back(stp);
stp.v=-1;
lne[d+1].push_back(stp);
}
for(int i=1;i<=q;i++){
int a,b; node2 stp;
read(a),read(b);
stp.p=a,stp.id=i;
ask[b].push_back(stp);
}
for(int i=1;i<=m;i++){
int len=lne[i].size();
for(int j=0;j<len;j++)
add(lne[i][j].up , lne[i][j].v),
add(lne[i][j].low+1,-lne[i][j].v);
len=ask[i].size();
for(int j=0;j<len;j++)
ans[ask[i][j].id]=srch(ask[i][j].p);
}
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}
//可持久线段树k小
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3000010;
struct node{
int l;
int r;
int sum;
}t[maxn<<2];
struct Node{
int p;
int id;
}Nod[maxn<<2];
int n;
int rt[maxn];
int a[maxn];
int v[maxn];
int m;
int cnt;
inline bool cmp(const Node &x,const Node &y) {
return x.p < y.p;
}
inline void build(int l,int r,int &p,int pos) {
++cnt;
t[cnt] = t[p];
p = cnt;
++t[p].sum;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) {
build(l,mid,t[p].l,pos);
}
else {
build(mid+1,r,t[p].r,pos);
}
return;
}
inline int query(int l,int r,int L,int R,int k) {
if(l == r) return l;
int c = t[t[R].l].sum - t[t[L].l].sum;
int mid = (l + r) >> 1;
if(c >= k) {
return query(l,mid,t[L].l,t[R].l,k);
}
else {
return query(mid +1 ,r,t[L].r,t[R].r,k - c);
}
}
int l,r,k;
int main (){
cin >> n >> m;
for(int i = 1;i <= n; ++i) {
cin >> Nod[i].p;
Nod[i].id = i;
}
sort(Nod+1,Nod+n+1,cmp);
for(int i = 1;i <= n; ++i) {
a[Nod[i].id] = i;
v[i] = Nod[i].p;
}
for(int i = 1;i <= m; ++i) {
rt[i] = rt[i - 1];
build(1,n,rt[i],a[i]);
}
while(m--) {
cin >> l >> r >> k;
cout<<v[query(1,n,rt[l-1],rt[r],k)]<<endl;
}
return 0;
}
//可持久线段树历史区间最大,历史单点修改
#include<cstdio>
const int maxn=1e4+10;
const int maxq=1e5+10;
int n,q,ts,ks;
int a,b,c,d;
int tt[maxq];
struct tree{int s,l,r,mid,lp,rp;}t[maxq<<4];
inline int min_(int x,int y){return x<y?x:y;}
inline int max_(int x,int y){return x>y?x:y;}
void build(int l,int r,int k){
t[k].l=l,t[k].r=r;
if(l==r){scanf("%d",&t[k].s);return;}
t[k].mid=l+r>>1,t[k].lp=++ts,t[k].rp=++ts;
build(l,t[k].mid,t[k].lp);
build(t[k].mid+1,r,t[k].rp);
t[k].s=max_(t[t[k].lp].s,t[t[k].rp].s);
}
void change(int k,int nk){
t[nk].l=t[k].l,t[nk].r=t[k].r;
if(t[k].l==t[k].r){t[nk].s=d;return;}
t[nk].mid=t[k].mid;
if(c<=t[k].mid){
t[nk].lp=++ts,t[nk].rp=t[k].rp;
change(t[k].lp,t[nk].lp);
}
else{
t[nk].rp=++ts,t[nk].lp=t[k].lp;
change(t[k].rp,t[nk].rp);
}
t[nk].s=max_(t[t[nk].lp].s,t[t[nk].rp].s);
}
int search(int k,int l,int r){
if(t[k].l==l&&t[k].r==r) return t[k].s;
int ans=0;
if(l<=t[k].mid) ans=search(t[k].lp,l,min_(r,t[k].mid));
if(r>t[k].mid) ans=max_(ans,search(t[k].rp,max_(l,t[k].mid+1),r));
return ans;
}
int main(){
scanf("%d%d",&n,&q);
build(1,n,tt[++ks]);
while(q--){
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a){
tt[++ks]=++ts;
change(tt[b],tt[ks]);
}
else printf("%d\n",search(tt[b],c,d));
}
return 0;
}
//线段树扫描线
// luogu-judger-enable-o2
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define getchar() getchar()_locked
#define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
char BB[1<<15];
char *S=BB;
char *T=BB;
using namespace std;
const int Maxn=4005;
const int Maxp=1e5+5;
struct node{
int up,low,v;
};
struct node2{
int p,id;
};
struct node3{
int l,r,sum,lazy;
}tr[4*Maxn];
int ans[Maxp];
vector<node> lne[Maxn];
vector<node2> ask[Maxn];
inline void read(int &x){
x=0; int f=1; char ch;
do{ch=getchar(); if(ch=='-') f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0'; ch=getchar();} while(ch>='0'&&ch<='9');
x*=f;
}
void build(int p,int x,int y){
tr[p].l=x,tr[p].r=y,tr[p].sum=0,tr[p].lazy=0;
if(x==y) return ;
int mid=(x+y)/2;
build(p*2,x,mid),build(p*2+1,mid+1,y);
}
void push_down(int p){
if(!tr[p].lazy) return ;
tr[p * 2].sum+=(tr[p * 2].r-tr[p * 2].l+1)*tr[p].lazy;
tr[p*2+1].sum+=(tr[p*2+1].r-tr[p*2+1].l+1)*tr[p].lazy;
tr[p * 2].lazy+=tr[p].lazy;
tr[p*2+1].lazy+=tr[p].lazy;
tr[p].lazy=0;
}
void add(int p,int x,int y,int v){
int nl=tr[p].l,nr=tr[p].r;
if(nl==nr){
tr[p].sum+=(nr-nl+1)*v;
tr[p].lazy+=v;
return ;
}
push_down(p);
int mid=(nl+nr)/2;
if(y<=mid) add(p*2,x,y,v);
else if(x>mid) add(p*2+1,x,y,v);
else add(p*2,x,mid,v),add(p*2+1,mid+1,y,v);
tr[p].sum=tr[p*2].sum+tr[p*2+1].sum;
return ;
}
int srch(int p,int x){
int nl=tr[p].l,nr=tr[p].r;
if(nl==nr)
return tr[p].sum;
push_down(p);
int mid=(nl+nr)/2;
if(x<=mid) return srch(p*2,x);
else return srch(p*2+1,x);
}
int main(){
int n,m,p,q;
read(n),read(m),read(p),read(q);
build(1,1,n);
for(int i=1;i<=p;i++){
int a,b,c,d;
read(a),read(b),read(c),read(d);
node stp;
stp.up=a,stp.low=c,stp.v=1;
lne[b].push_back(stp);
stp.v=-1;
lne[d+1].push_back(stp);
}
for(int i=1;i<=q;i++){
int a,b; node2 stp;
read(a),read(b);
stp.p=a,stp.id=i;
ask[b].push_back(stp);
}
for(int i=1;i<=m;i++){
int len=lne[i].size();
for(int j=0;j<len;j++)
add(1,lne[i][j].up,lne[i][j].low,lne[i][j].v);
len=ask[i].size();
for(int j=0;j<len;j++)
ans[ask[i][j].id]=srch(1,ask[i][j].p);
}
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}
//待修改k小
// luogu-judger-enable-o2
//bzoj 3065
#include<bits/stdc++.h>
using namespace std;
#define MAXN 700005
#define MAXV 700005
#define MAXP 20009999
#define ALPHA 0.68
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
void getopt(char &c) {
c = getchar();
while (c != 'Q' && c != 'I' && c != 'M')
c = getchar();
}
struct Segment_Tree {
int now, root[MAXN];
int top, mem[MAXP];
int lc[MAXP], rc[MAXP], sum[MAXP];
void init(int n) {
for (int i = 1; i <= n; i++)
mem[i] = n - i + 1;
top = n;
}
int new_node() {
int tmp = mem[top--];
lc[tmp] = rc[tmp] = 0;
sum[tmp] = 0;
return tmp;
}
void recycle(int x) {
mem[++top] = x;
}
void dfs(int x) {
if (lc[x]) dfs(lc[x]);
if (rc[x]) dfs(rc[x]);
recycle(x);
}
void clear(int x) {
if (root[x]) dfs(root[x]);
root[x] = 0;
}
void modify(int &root, int l, int r, int pos, int delta) {
if (root == 0) root = new_node();
sum[root] += delta;
if (l == r) return;
int mid = (l + r) / 2;
if (mid >= pos) modify(lc[root], l, mid, pos, delta);
else modify(rc[root], mid + 1, r, pos, delta);
}
void modify(int x, int v, int d) {
modify(root[x], 0, MAXV, v, d);
}
int query(int k, int len, int *type, int *home) {
int l = 0, r = MAXV;
for (int i = 1; i <= len; i++)
home[i] = root[home[i]];
while (l < r) {
int mid = (l + r) / 2;
int tsum = 0;
for (int i = 1; i <= len; i++)
tsum += type[i] * sum[lc[home[i]]];
if (tsum >= k) {
r = mid;
for (int i = 1; i <= len; i++)
home[i] = lc[home[i]];
} else {
l = mid + 1;
k -= tsum;
for (int i = 1; i <= len; i++)
home[i] = rc[home[i]];
}
}
return l;
}
} SMT;
struct Scapegoat_Tree {
int root, reroot;
int len, tindex[MAXN];
int type[MAXN], home[MAXN];
int top, mem[MAXN];
int lc[MAXN], rc[MAXN];
int index[MAXN], size[MAXN];
void init(int n) {
for (int i = 1; i <= n; i++)
mem[i] = n - i + 1;
top = n;
}
int new_node() {
int tmp = mem[top--];
lc[tmp] = rc[tmp] = 0;
index[tmp] = 0;
size[tmp] = 0;
SMT.clear(tmp);
return tmp;
}
void recycle(int x) {
mem[++top] = x;
}
void update(int x) {
size[x] = 1;
size[x] += size[lc[x]];
size[x] += size[rc[x]];
}
void dfs(int root) {
if (root != reroot) recycle(root);
if (lc[root]) dfs(lc[root]);
tindex[++len] = index[root];
if (rc[root]) dfs(rc[root]);
}
void rebuild(int root, int l, int r) {
for (int i = l; i <= r; i++)
SMT.modify(root, tindex[i], 1);
int mid = (l + r) / 2;
index[root] = tindex[mid];
if (mid > l) {
lc[root] = new_node();
rebuild(lc[root], l, mid - 1);
}
if (mid < r) {
rc[root] = new_node();
rebuild(rc[root], mid + 1, r);
}
update(root);
}
void rebuild(int root) {
len = 0;
dfs(root);
lc[root] = rc[root] = 0;
index[root] = size[root] = 0;
SMT.clear(root);
rebuild(root, 1, len);
}
void index_init(int n, int *a) {
for (int i = 1; i <= n; i++)
tindex[i] = a[i];
root = new_node();
rebuild(root, 1, n);
}
bool unbalance(int root) {
return max(size[lc[root]], size[rc[root]]) > size[root] * ALPHA + 1;
}
void insert(int &root, int pos, int value) {
if (root == 0) {
root = new_node();
index[root] = value;
size[root] = 1;
SMT.modify(root, value, 1);
return;
}
SMT.modify(root, value, 1); size[root]++;
if (pos <= size[lc[root]] + 1) insert(lc[root], pos, value);
else insert(rc[root], pos - size[lc[root]] - 1, value);
if (unbalance(root)) reroot = root;
}
void insert(int pos, int value) {
reroot = 0;
insert(root, pos, value);
if (reroot) rebuild(reroot);
}
int modify(int root, int pos, int value) { /*Return Value: Old Index*/
SMT.modify(root, value, 1);
if (pos <= size[lc[root]]) {
int tmp = modify(lc[root], pos, value);
SMT.modify(root, tmp, -1);
return tmp;
} else {
pos -= size[lc[root]];
if (pos == 1) {
int tmp = index[root];
index[root] = value;
SMT.modify(root, tmp, -1);
return tmp;
}
int tmp = modify(rc[root], pos - 1, value);
SMT.modify(root, tmp, -1);
return tmp;
}
}
void modify(int pos, int value) {
modify(root, pos, value);
}
void getquery(int root, int l, int r, int t) {
int mid = size[lc[root]] + 1;
if (mid > r) getquery(lc[root], l, r, t);
else if (mid < l) getquery(rc[root], l - mid, r - mid, t);
else {
len++; home[len] = root; type[len] = t;
if (l != 1) getquery(lc[root], 1, l - 1, -t);
if (r != size[root]) getquery(rc[root], r - size[lc[root]], size[root] - size[lc[root]] - 1, -t);
}
}
int query(int l, int r, int k) {
len = 0;
getquery(root, l, r, 1);
return SMT.query(k, len, type, home);
}
} SGT;
int num[MAXN];
int main() {
SMT.init(MAXP - 1);
SGT.init(MAXN - 1);
int lastans = 0;
int n; read(n);
for (int i = 1; i <= n; i++)
read(num[i]);
SGT.index_init(n, num);
int m; read(m);
for (int i = 1; i <= m; i++) {
char opt; int l, r, v;
getopt(opt);
if (opt == 'I') {
read(l), read(v);
l ^= lastans;
v ^= lastans;
SGT.insert(l, v);
}
if (opt == 'Q') {
read(l), read(r), read(v);
l ^= lastans;
r ^= lastans;
v ^= lastans;
printf("%d\n", lastans = SGT.query(l, r, v));
}
if (opt == 'M') {
read(l), read(v);
l ^= lastans;
v ^= lastans;
SGT.modify(l, v);
}
}
return 0;
}
- 平衡树
#include <cstdio>
#include <cstdlib>
#include <ctime>
#define N 500005
using namespace std;
int inline read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int ch[N][2],val[N],pri[N],siz[N],sz;
void update(int x){siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];}
int new_node(int v)
{
siz[++sz]=1;
val[sz]=v;
pri[sz]=rand();
return sz;
}
int merge(int x,int y)
{
if (!x || !y) return x+y;
if (pri[x]<pri[y])
{
ch[x][1]=merge(ch[x][1],y);
update(x);
return x;
}
else
{
ch[y][0]=merge(x,ch[y][0]);
update(y);
return y;
}
}
void split(int now,int k,int &x,int &y)
{
if (!now) x=y=0;
else
{
if (val[now]<=k)
x=now,split(ch[now][1],k,ch[now][1],y);
else
y=now,split(ch[now][0],k,x,ch[now][0]);
update(now);
}
}
int kth(int now,int k)
{
while(1)
{
if (k<=siz[ch[now][0]])
now=ch[now][0];
else
if (k==siz[ch[now][0]]+1)
return now;
else
k-=siz[ch[now][0]]+1,now=ch[now][1];
}
}
main()
{
srand((unsigned)time(NULL));
int T,com,x,y,z,a,b,root=0;
scanf("%d",&T);
while(T--)
{
com=read(),a=read();
if (com==1)
{
split(root,a,x,y);
root=merge(merge(x,new_node(a)),y);
}
else
if (com==2)
{
split(root,a,x,z);
split(x,a-1,x,y);
y=merge(ch[y][0],ch[y][1]);
root=merge(merge(x,y),z);
}
else
if (com==3)
{
split(root,a-1,x,y);
printf("%d\n",siz[x]+1);
root=merge(x,y);
}
else
if (com==4)
printf("%d\n",val[kth(root,a)]);
else
if (com==5)
{
split(root,a-1,x,y);
printf("%d\n",val[kth(x,siz[x])]);
root=merge(x,y);
}
else
{
split(root,a,x,y);
printf("%d\n",val[kth(y,1)]);
root=merge(x,y);
}
}
}
//fhq treap
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<ctime>
#include<algorithm>
using namespace std;
int root,n,a,b,tmp;
int sz;
struct treap {
int sz,tot,w,rnd,ch[2];
int lc,rc;
} t[1000500];
void update(int x) {
t[x].sz=t[t[x].ch[0]].sz+t[t[x].ch[1]].sz+t[x].tot;
}
void turn(int &x,int k) {
int y=t[x].ch[k^1];
t[x].ch[k^1]=t[y].ch[k];
t[y].ch[k]=x;
update(x);
update(y);
x=y;
}
void insert(int &x,int w) {
if(!x) {
t[++sz].w=w;
t[sz].rnd=rand();
t[sz].tot=t[sz].sz=1;
x=sz;
} else {
if(t[x].sz++,t[x].w==w)t[x].tot++;
else if(insert(t[x].ch[tmp=w>t[x].w],w),t[t[x].ch[tmp]].rnd>t[x].rnd) {
turn(x,tmp^1);
}
}
}
void del(int &x,int w) {
if(!x)return;
if(t[x].w==w) {
if(t[x].tot>1)t[x].tot--,t[x].sz--;
else {
if(!(t[x].ch[0]&&t[x].ch[1]))x=t[x].ch[0]|t[x].ch[1];
else
turn(x,tmp=t[t[x].ch[0]].rnd>t[t[x].ch[1]].rnd),t[x].sz--,del(t[x].ch[tmp],w);
}
} else t[x].sz--,del(t[x].ch[w>t[x].w],w);
}
int rank1(int x,int w) {
if(t[x].w==w)return t[t[x].ch[0]].sz+1;
if(t[x].w<w)return t[t[x].ch[0]].sz+t[x].tot+rank1(t[x].ch[1],w);
else return rank1(t[x].ch[0],w);
}
int kth(int x,int w) {
if(!x)return 0;
if(w<=t[t[x].ch[0]].sz)return kth(t[x].ch[0],w);
else if(w>t[t[x].ch[0]].sz+t[x].tot)return kth(t[x].ch[1],w-t[t[x].ch[0]].sz-t[x].tot);
else return t[x].w;
}
int pre(int v) {
insert(root,v);
tmp=kth(root,rank1(root,v)-1);
del(root,v);
return tmp;
}
int find(int x,int v) {
return t[x].w==v?x:find(t[x].ch[t[x].w<v],v);
}
int sub(int v) {
insert(root,v);
tmp=kth(root,rank1(root,v)+t[find(root,v)].tot);
del(root,v);
return tmp;
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d%d",&a,&b);
if(a==1)insert(root,b);
if(a==2)del(root,b);
if(a==3)printf("%d\n",rank1(root,b));
if(a==4)printf("%d\n",kth(root,b));
if(a==5)printf("%d\n",pre(b));
if(a==6)printf("%d\n",sub(b));
}
}
//treap
#include<cstdio>
struct SBT {
int v, sz, ch[2], cnt;
} t[300005];
int n, cnt, root;
#define Upd(k) {\
t[k].sz = t[t[k].ch[0]].sz + t[t[k].ch[1]].sz + t[k].cnt;\
}
void rot(int &k, bool f) {
int p = t[k].ch[f]; t[k].ch[f] = t[p].ch[!f]; t[p].ch[!f] = k;
Upd(k); Upd(p); k = p;
}
inline void mt(int &k,bool f)
{
if(!k) return;
if(t[t[k].ch[f^1]].sz < t[t[t[k].ch[f]].ch[f]].sz) rot(k, f);
else if(t[t[k].ch[f^1]].sz < t[t[t[k].ch[f]].ch[f^1]].sz) { rot(t[k].ch[f], f^1); rot(k, f); }
else return;
mt(t[k].ch[f],f);
mt(k,f);
}
void Ins(int &k, int x) {
if(!k) {k = ++ cnt; t[k].sz = t[k].cnt = 1; t[k].v = x; return; }
++ t[k].sz;
if(t[k].v == x) {++ t[k].cnt; return;}
Ins(t[k].ch[t[k].v < x], x);
mt(k, t[k].v < x);
}
int Del(int &k, int x) {
if(!k) return k;
int tmp;
if(t[k].v == x) {
if(t[k].cnt > 1) {-- t[k].cnt; --t[k].sz; return k;}
else if(!(t[k].ch[0]*t[k].ch[1])) {k = t[k].ch[0]+t[k].ch[1];}
else { tmp = Del(t[k].ch[0], x+1); t[k].cnt = t[tmp].cnt; t[k].v = t[tmp].v; Upd(k); return k; }
}
else if((t[k].v < x && !t[k].ch[1]) || (t[k].v > x && ! t[k].ch[0])) { tmp = k; k = t[k].ch[0]; Upd(k); return tmp; }
else tmp = Del(t[k].ch[t[k].v < x], x);
Upd(k); return tmp;
}
int Ran(int k,int x) {
if(k==0)return 0;
if(t[k].v==x)return t[t[k].ch[0]].sz+1;
else if(x>t[k].v)
return t[t[k].ch[0]].sz+t[k].cnt+Ran(t[k].ch[1],x);
else return Ran(t[k].ch[0],x);
}
int Kth(int k,int x) {
if(k==0)return 0;
if(x<=t[t[k].ch[0]].sz)
return Kth(t[k].ch[0],x);
else if(x>t[t[k].ch[0]].sz+t[k].cnt)
return Kth(t[k].ch[1],x-t[t[k].ch[0]].sz-t[k].cnt);
else return t[k].v;
}
int ans;
void pred(int k,int x) {
if(k==0)return;
if(t[k].v<x) {
ans=k;
pred(t[k].ch[1],x);
} else pred(t[k].ch[0],x);
}
void succ(int k,int x) {
if(k==0)return;
if(t[k].v>x) {
ans=k;
succ(t[k].ch[0],x);
} else succ(t[k].ch[1],x);
}
char c, f;
inline void GET(int &n) {
n = 0; f = 1;
do {c = getchar(); if(c == '-') f = -1;} while(c > '9' || c < '0');
while(c >= '0' && c <= '9') {n=n*10+c-'0';c=getchar();}
n *= f;
}
int main() {
GET(n);
int opt,x;
for(int i=1; i<=n; i++) {
GET(opt); GET(x);
switch(opt) {
case 1: Ins(root,x); break;
case 2: Del(root,x); break;
case 3: printf("%d\n",Ran(root,x)); break;
case 4: printf("%d\n",Kth(root,x)); break;
case 5: ans=0; pred(root,x); printf("%d\n",t[ans].v); break;
case 6: ans=0; succ(root,x); printf("%d\n",t[ans].v); break;
}
}
return 0;
}
//SBT
#include <cstdio>
#define Maxn 1000000
using namespace std;
int f[Maxn];//father
int ch[Maxn][2];//child ; 0 for left ; 1 for right
int key[Maxn];//key
int cnt[Maxn];//value
int siz[Maxn];//size of subtree
int sz,root;//size of tree and root
//clear the ndoe
void clear(int x)
{
ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0;
}
//rightson return 1;left son return 0
int getson(int x)
{
return ch[f[x]][1]==x;
}
//update the size
void update(int x)
{
siz[x]=cnt[x];
if (ch[x][0]) siz[x]+=siz[ch[x][0]];
if (ch[x][1]) siz[x]+=siz[ch[x][1]];
}
//retation
int rotate(int x)
{
int fa=f[x],fafa=f[fa],k=getson(x);
ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa;
ch[x][k^1]=fa;f[fa]=x;
f[x]=fafa;
if (fafa)
ch[fafa][ch[fafa][1]==fa]=x;
update(fa);update(x);
}
//rotate until x is the root
void splay(int x)
{
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate(getson(x)==getson(fa) ? fa : x);
root=x;
}
int pre()
{
int now=ch[root][0];
while(ch[now][1])
now=ch[now][1];
return now;
}
int nex()
{
int now=ch[root][1];
while(ch[now][0])
now=ch[now][0];
return now;
}
//find x's pos
int findpos(int v)
{
int now=root,ans=0;
while(1)
{
if (v<key[now])
now=ch[now][0];
else
{
ans+=ch[now][0]?siz[ch[now][0]]:0;
if (v==key[now])
{
splay(now);
return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
//find pos's x
int findx(int x)
{
int now=root;
while(1)
{
if (ch[now][0] && x<=siz[ch[now][0]])
now=ch[now][0];
else
{
int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
if (x<=temp)
return key[now];
x-=temp;
now=ch[now][1];
}
}
}
//ceate a new splay node
void create(int v)
{
sz++;
ch[sz][0]=ch[sz][1]=f[sz]=0;
key[sz]=v;
cnt[sz]=1;
siz[sz]=1;
//root=sz;
}
//insert a node
void insert(int v)
{
if (!root)
create(v),root=sz;
else
{
int now=root,fa=0;
while(1)
{
if (key[now]==v)
{
cnt[now]++;
update(now);update(fa);
splay(now);
break;
}
fa=now;
now=ch[fa][v>key[fa]];
if (!now)
{
create(v);
f[sz]=fa;
ch[fa][v>key[fa]]=sz;
update(fa);
splay(sz);
break;
}
}
}
}
void del(int x)
{
int t=findpos(x);
if (cnt[root]>1)
{
cnt[root]--;
update(root);
return;
}
//none
if (!ch[root][0] && !ch[root][1])
{
clear(root);
root=0;
return;
}
//one
if (!ch[root][1])
{
int temp=root;
root=ch[root][0];
f[root]=0;
clear(temp);
return;
}
else
if (!ch[root][0])
{
int temp=root;
root=ch[root][1];
f[root]=0;
clear(temp);
return;
}
//two
int pre1=pre(),temp=root;
splay(pre1);
f[ch[temp][1]]=root;
ch[root][1]=ch[temp][1];
clear(temp);
update(root);
}
int main()
{
int n,opt,x;
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%d%d",&opt,&x);
switch(opt)
{
case 1: insert(x); break;
case 2: del(x); break;
case 3: printf("%d\n",findpos(x)); break;
case 4: printf("%d\n",findx(x)); break;
case 5: insert(x); printf("%d\n",key[pre()]); del(x); break;
case 6: insert(x); printf("%d\n",key[nex()]); del(x); break;
}
}
}
//splay
#include<cstdio>
#include<algorithm>
using namespace std;
const double r=0.78;
const int maxn=100010,oo=0x3f3f3f3f;
int rd()
{
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*10+c-'0';
c=getchar();
}
return x*f;
}
int son[maxn][2],siz[maxn],num[maxn],w[maxn],cnt[maxn],
fid[maxn],fw[maxn],fcnt[maxn],sta[maxn],
tot,clo,rt,id,fa,b;
void pause()
{
int x;
x=1;
}
void upd(int u)
{
if (!u) return;
siz[u]=siz[son[u][0]]+siz[son[u][1]]+1;
num[u]=num[son[u][0]]+num[son[u][1]]+cnt[u];
}
void check(int u)
{
if (!u) return;
if (siz[son[u][0]]>siz[u]*r||siz[son[u][1]]>siz[u]*r)
id=u,fa=-1;
if (son[u][0]==id)
{
fa=u;
b=0;
}
if (son[u][1]==id)
{
fa=u;
b=1;
}
}
void dfs(int u)
{
if (!u) return;
dfs(son[u][0]);
clo++;
fid[clo]=u;
fw[clo]=w[u];
fcnt[clo]=cnt[u];
dfs(son[u][1]);
}
int build(int L,int R)
{
if (L>R) return 0;
int mid=L+R>>1,u;
u=fid[mid];
w[u]=fw[mid];
cnt[u]=fcnt[mid];
son[u][0]=build(L,mid-1);
son[u][1]=build(mid+1,R);
upd(u);
return u;
}
int solve(int u)
{
/*if (siz[son[u][0]]==-1) pause();
printf("%d:%dvs%d\n",siz[u],siz[son[u][0]],siz[son[u][1]]);*/
clo=0;
dfs(u);
return build(1,clo);
}
int ins(int u,int x)
{
if (!u)
{
u=++tot;
w[u]=x;
cnt[u]=siz[u]=num[u]=1;
return u;
}
if (w[u]==x)
{
cnt[u]++;
num[u]++;
return u;
}
son[u][x>w[u]]=ins(son[u][x>w[u]],x);
upd(u);
check(u);
return u;
}
int del(int u,int x)
{
//if (x==-8195776) pause();
if (x==w[u])
{
cnt[u]--;
if (!cnt[u])
{
if (son[u][0]*son[u][1]==0) u=son[u][0]+son[u][1];
else
{
int fl=siz[son[u][0]]<siz[son[u][1]];
int p=son[u][fl],top=0;
while (son[p][fl^1]) sta[++top]=p,p=son[p][fl^1];
if (top)
{
son[sta[top]][fl^1]=son[p][fl];
son[p][0]=son[u][0];
son[p][1]=son[u][1];
for (;top;top--) upd(sta[top]);
}
else son[p][fl^1]=son[u][fl^1];
u=p;
}
}
upd(u);
check(u);
return u;
}
son[u][x>w[u]]=del(son[u][x>w[u]],x);
upd(u);
check(u);
return u;
}
int get_rank(int u,int x)
{
if (!u) return 0;
if (x==w[u]) return num[son[u][0]]+1;
if (x<w[u]) return get_rank(son[u][0],x);
return cnt[u]+num[son[u][0]]+get_rank(son[u][1],x);
}
int qry(int u,int x)
{
if (x<=num[son[u][0]]) return qry(son[u][0],x);
if (x<=cnt[u]+num[son[u][0]]) return w[u];
return qry(son[u][1],x-(cnt[u]+num[son[u][0]]));
}
int pre(int u,int x)
{
if (!u) return -oo;
if (w[u]>=x) return pre(son[u][0],x);
return max(w[u],pre(son[u][1],x));
}
int succ(int u,int x)
{
if (!u) return oo;
if (w[u]<=x) return succ(son[u][1],x);
return min(w[u],succ(son[u][0],x));
}
int main()
{
/*freopen("phs.in","r",stdin);
freopen("phs.out","w",stdout);*/
int n,opt;
n=rd();
while (n--)
{
/*if (n%3000==0) printf("%d\n",n);
if (n%5000==0) pause();*/
opt=rd();
switch (opt)
{
case 1:
id=-1;
rt=ins(rt,rd());
if (id>0)
{
if (fa==-1) rt=solve(id);
else son[fa][b]=solve(id);
}
break;
case 2:
id=-1;
rt=del(rt,rd());
if (id>0)
{
if (fa==-1) rt=solve(id);
else son[fa][b]=solve(id);
}
break;
//default:rd();break;
case 3:printf("%d\n",get_rank(rt,rd()));break;
case 4:printf("%d\n",qry(rt,rd()));break;
case 5:printf("%d\n",pre(rt,rd()));break;
case 6:printf("%d\n",succ(rt,rd()));break;
/*case 3:get_rank8(rt,rd());break;
case 4:qry(rt,rd());break;
case 5:pre(rt,rd());break;
case 6:succ(rt,rd());break;*/
}
}
}
//SGT
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<ctime>
using namespace std;
const int N=5e5+10;
int n,rt[N],cnt;
struct Node{
int ch[2];
int rnd,sz,v;
}t[N*50];
inline int read()
{
int x=0,t=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*t;
}
inline int copynode(int x)
{
t[++cnt]=t[x];
return cnt;
}
inline int newnode(int x)
{
t[++cnt].v=x;t[cnt].sz=1;t[cnt].rnd=rand();
return cnt;
}
inline void update(int k)
{
if(k)
t[k].sz=t[t[k].ch[0]].sz+t[t[k].ch[1]].sz+1;
}
inline void split(int now,int k,int &x,int &y)
{
if(!now) {x=0;y=0;return;}
if(t[now].v<=k){
x=copynode(now);
split(t[x].ch[1],k,t[x].ch[1],y);
}else{
y=copynode(now);
split(t[y].ch[0],k,x,t[y].ch[0]);
}
update(x);update(y);
}
inline int merge(int x,int y)
{
if(!x || !y) return x+y;
if(t[x].rnd<t[y].rnd){
int z=copynode(x);
t[z].ch[1]=merge(t[z].ch[1],y);
update(z);
return z;
}else{
int z=copynode(y);
t[z].ch[0]=merge(x,t[z].ch[0]);
update(z);
return z;
}
}
inline void insert(int now,int k)
{
int x=0,y=0,z=0;
split(rt[now],k,x,y);
z=newnode(k);
rt[now]=merge(merge(x,z),y);
}
inline void del(int now,int k)
{
int x=0,y=0,z=0;
split(rt[now],k,x,y);
split(x,k-1,x,z);
z=merge(t[z].ch[0],t[z].ch[1]);
rt[now]=merge(merge(x,z),y);
}
inline int rnk(int now,int k)
{
int x=0,y=0;
split(rt[now],k-1,x,y);
return t[x].sz+1;
}
inline int kth(int x,int k)
{
while(1){
if(t[t[x].ch[0]].sz+1 ==k) return t[x].v;
else if(t[t[x].ch[0]].sz>=k) x=t[x].ch[0];
else {k-=(t[t[x].ch[0]].sz+1);x=t[x].ch[1];}
//1-> cause the same are not on the same
}
}
inline int pre(int now,int k)
{
int x=0,y=0,z=0;
split(rt[now],k-1,x,y);
if(!x) return -2147483647;
return kth(x,t[x].sz);
}
inline int suf(int now,int k)
{
int x=0,y=0,z=0;
split(rt[now],k,x,y);
if(!y) return 2147483647;
return kth(y,1);
}
int main(){
srand(time(0));
n=read();
for(int i=1;i<=n;i++){
int in=read(),op=read();
rt[i]=rt[in];
if(op==1) insert(i,read());
else
if(op==2) del(i,read());
else
if(op==3) printf("%d\n",rnk(i,read()));
else
if(op==4) printf("%d\n",kth(rt[i],read()));
else
if(op==5) printf("%d\n",pre(i,read()));
else
printf("%d\n",suf(i,read()));
}
return 0;
}
//可持久化平衡树
- 并查集
#include<iostream>
#include<cstdio>
using namespace std;
int f[2000010];
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
}
void merge(int a,int b){
int f1=find(a),f2=find(b);
if(f1!=f2){
f[f2]=f1;
}
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i;
while(m--){
int opt;
cin>>opt;
switch(opt){
case(1):{
int a,b;
cin>>a>>b;
merge(a,b);
break;
}
case(2):{
int a,b;
cin>>a>>b;
if(find(a)==find(b)){
cout<<"Y"<<endl;
}
else cout<<"N"<<endl;
}
}
}
}
#include<cstdio>
#include<iostream>
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
int n,m,sz,last;
int root[200005],ls[10000005],rs[10000005],v[10000005],deep[10000005];
void build(int &k,int l,int r)
{
if(!k)k=++sz;
if(l==r){v[k]=l;return;}
int mid=(l+r)>>1;
build(ls[k],l,mid);
build(rs[k],mid+1,r);
}
void modify(int l,int r,int x,int &y,int pos,int val)
{
y=++sz;
if(l==r){v[y]=val;return;}
ls[y]=ls[x];rs[y]=rs[x];
int mid=(l+r)>>1;
if(pos<=mid)
modify(l,mid,ls[x],ls[y],pos,val);
else modify(mid+1,r,rs[x],rs[y],pos,val);
}
int query(int k,int l,int r,int pos)
{
if(l==r)return k;
int mid=(l+r)>>1;
if(pos<=mid)return query(ls[k],l,mid,pos);
else return query(rs[k],mid+1,r,pos);
}
void add(int k,int l,int r,int pos)
{
if(l==r){deep[k]++;return;}
int mid=(l+r)>>1;
if(pos<=mid)add(ls[k],l,mid,pos);
else add(rs[k],mid+1,r,pos);
}
int find(int k,int x)
{
int p=query(k,1,n,x);
if(x==v[p])return p;
return find(k,v[p]);
}
int main()
{
n=read();m=read();
build(root[0],1,n);
int f,k,a,b;
for(int i=1;i<=m;i++)
{
f=read();
if(f==1)
{
root[i]=root[i-1];
a=read();b=read();a=a^last;b=b^last;
int p=find(root[i],a),q=find(root[i],b);
if(v[p]==v[q])continue;
if(deep[p]>deep[q])swap(p,q);
modify(1,n,root[i-1],root[i],v[p],v[q]);
if(deep[p]==deep[q])add(root[i],1,n,v[q]);
}
if(f==2)
{k=read();k=k^last;root[i]=root[k];}
if(f==3)
{
root[i]=root[i-1];
a=read();b=read();a=a^last;b=b^last;
int p=find(root[i],a),q=find(root[i],b);
if(v[p]==v[q])last=1;
else last=0;
printf("%d\n",last);
}
}
return 0;
}
//好吧其实可持久并查集和并查集并没什么太大关系,主席树维护持久数组
//留坑二维并查集
- 树链剖分
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree{int l,r,sum,book;}tr[400005];
struct edge{int to,nxt;}e[200005];
int head[100005],tot,cnt;
int p[100005],y[100005],x[100005],si[100005];
int dep[100005],fa[100005],bl[100005];
int n,m,ans,mod,root;
void add(int u,int v){e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;}
void dfs(int u){
si[u]=1;
for(int v,c=head[u];c;c=e[c].nxt){
v=e[c].to;
if(v==fa[u])continue;
dep[v]=dep[u]+1;fa[v]=u;
dfs(v);
si[u]+=si[v];
}
}
void dfs2(int u,int blo){
p[u]=++cnt;bl[u]=blo;y[p[u]]=x[u];
int k=0;
for(int v,c=head[u];c;c=e[c].nxt){
v=e[c].to;
if(dep[v]!=dep[u]+1)continue;
if(si[v]>si[k])k=v;
}
if(k==0)return;
dfs2(k,blo);
for(int v,c=head[u];c;c=e[c].nxt){
if(e[c].to==k)continue;
v=e[c].to;
if(dep[v]!=dep[u]+1)continue;
dfs2(v,v);
}
}
void pushdown(int now){
tr[now*2].book=(tr[now].book+tr[now*2].book)%mod;
tr[now*2+1].book=(tr[now].book+tr[now*2+1].book)%mod;
tr[now].sum=(tr[now].sum+(tr[now].r-tr[now].l+1)*tr[now].book%mod)%mod;
tr[now].book=0;
}
void tr_build(int l,int r,int now){
tr[now].l=l;tr[now].r=r;
if(l==r){
tr[now].sum=y[l];
return ;
}
else{
int mid=(l+r)/2;
tr_build(l,mid,now*2);
tr_build(mid+1,r,now*2+1);
tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
}
}
void bt_add(int l,int r,int c,int now){
if(l==tr[now].l&&r==tr[now].r){
if(l==r)tr[now].sum=(tr[now].sum+c)%mod;
else tr[now].book=(tr[now].book+c)%mod;
return;
}
tr[now].sum=(tr[now].sum+(r-l+1)*c%mod)%mod;
int mid=(tr[now].l+tr[now].r)/2;
if(l>mid)bt_add(l,r,c,now*2+1);
else if(r<=mid)bt_add(l,r,c,now*2);
else{
bt_add(l,mid,c,now*2);
bt_add(mid+1,r,c,now*2+1);
}
}
void bt_ser(int l,int r,int now){
if(l==tr[now].l&&r==tr[now].r){
ans=(ans+tr[now].sum+(r-l+1)*tr[now].book%mod)%mod;
return;
}
pushdown(now);
int mid=(tr[now].l+tr[now].r)/2;
if(l>mid)bt_ser(l,r,now*2+1);
else if(r<=mid)bt_ser(l,r,now*2);
else{
bt_ser(l,mid,now*2);
bt_ser(mid+1,r,now*2+1);
}
}
void si_add(int u,int v,int s){
while(bl[u]!=bl[v]){
if(dep[bl[u]]>dep[bl[v]])swap(u,v);
bt_add(p[bl[v]],p[v],s,1);
v=fa[bl[v]];
}
if(dep[u]>dep[v])swap(u,v);
bt_add(p[u],p[v],s,1);
}
void si_sum(int u,int v){
ans=0;
while(bl[u]!=bl[v]){
if(dep[bl[u]]>dep[bl[v]])swap(u,v);
bt_ser(p[bl[v]],p[v],1);
v=fa[bl[v]];
}
if(dep[u]>dep[v])swap(u,v);
bt_ser(p[u],p[v],1);
printf("%d\n",ans);
}
void tr_add(int u,int s){bt_add(p[u],p[u]+si[u]-1,s,1);}
void tr_sum(int u){
ans=0;
bt_ser(p[u],p[u]+si[u]-1,1);
printf("%d\n",ans);
}
int main(){
scanf("%d%d%d%d",&n,&m,&root,&mod);
for(int i=1;i<=n;++i)scanf("%d",&x[i]);
for(int i=1,u,v;i<n;++i){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(root);dfs2(root,root);
tr_build(1,n,1);
for(int i=1,opt,u,v,s;i<=m;++i){
scanf("%d%d",&opt,&u);
if(opt==1){
scanf("%d%d",&v,&s);
si_add(u,v,s%mod);
}
else if(opt==2){
scanf("%d",&v);
si_sum(u,v);
}
else if(opt==3){
scanf("%d",&s);
tr_add(u,s%mod);
}
else {tr_sum(u);}
}
return 0;
}
- 树状数组
懒得写了
- 动态树
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=300005;
int n,m,top;
int ch[maxn][2],rev[maxn],que[maxn];
int fa[maxn],val[maxn],sum[maxn];
bool isroot(int x){
return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}
void pushup(int x){
sum[x]=sum[ch[x][0]]^val[x]^sum[ch[x][1]];
}
void pushdown(int x){
if(rev[x]){
rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
void rotat(int x){
int y=fa[x],z=fa[y],l,r;
if(ch[y][0]==x)l=0;else l=1;r=l^1;
if(!isroot(y)){
ch[z][ch[z][1]==y]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int i;
for(i=x;!isroot(i);i=fa[i]){
que[++top]=i;
}
que[++top]=i;
while(top)pushdown(que[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((ch[z][0]==y)^(ch[y][0]==x))rotat(x);
else rotat(y);
}
rotat(x);
}
}
void access(int x){
int lst=0;
while(x){
splay(x);ch[x][1]=lst;pushup(x);lst=x;x=fa[x];
}
}
void makeroot(int x){
access(x);splay(x);rev[x]^=1;
}
void link(int x,int y){
makeroot(x);fa[x]=y;pushup(y);
}
void cut(int x,int y){
makeroot(x);access(y);splay(y);
if(ch[y][0]==x){
ch[y][0]=fa[x]=0;pushup(y);
}
}
void change(int x,int y){
access(x);splay(x);val[x]=y;pushup(x);
}
int LCT_query(int x,int y){
makeroot(x);access(y);splay(y);
return sum[y];
}
int findroot(int x){
access(x);splay(x);
while(ch[x][0])x=ch[x][0];
return x;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&val[i]);
int opt,x,y;
for(int i=1;i<=m;++i){
scanf("%d%d%d",&opt,&x,&y);
switch(opt){
case 0:{
printf("%d\n",LCT_query(x,y));
break;
}
case 1:{
if(findroot(x)!=findroot(y))
link(x,y);
break;
}
case 2:{
cut(x,y);
break;
}
case 3:{
change(x,y);
break;
}
}
}
return 0;
}
- 点分治
//IOI2011Race
// luogu-judger-enable-o2
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 200010
#define maxk 1000010
#define INF 1000000009
struct edge{
int to,nxt,w;
}e[maxn<<1];
int n,root,k,sum,head[maxn],tot,tmp[maxk],dis[maxn],dep[maxn],ans=INF,vis[maxn],siz[maxn],g[maxn];
void add(int u,int v,int w){
e[++tot].to=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot;
}
void getroot(int u,int fa){
siz[u]=1;
g[u]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]||v==fa) continue;
getroot(v,u);
siz[u]+=siz[v];
g[u]=max(g[u],siz[v]);
}
g[u]=max(g[u],sum-siz[u]);
if(g[u]<g[root]) root=u;
}
void dfsdis(int u,int fa){
if(dis[u]<=k) ans=min(ans,tmp[k-dis[u]]+dep[u]);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]||v==fa) continue;
dis[v]=dis[u]+e[i].w;
dep[v]=dep[u]+1;
dfsdis(v,u);
}
}
void calc(int u,int fa,int p){
if(dis[u]<=k){
if(p) tmp[dis[u]]=min(tmp[dis[u]],dep[u]);
else tmp[dis[u]]=INF;
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]||v==fa) continue;
calc(v,u,p);
}
}
void dfs(int u){
vis[u]=1; tmp[0]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]) continue;
dis[v]=e[i].w; dep[v]=1;
dfsdis(v,0);
calc(v,0,1);
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]) continue;
calc(v,0,0);
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]) continue;
root=0;
sum=siz[v];
getroot(v,0);
dfs(root);
}
}
int main(){
scanf("%d %d",&n,&k);
for(int i=1;i<=k;++i) tmp[i]=INF;
for(int i=1;i<n;++i){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
++u;
++v;
add(u,v,w);
add(v,u,w);
}
root=0;
sum=g[0]=n;
getroot(1,0);
dfs(root);
if(ans!=INF) printf("%d",ans);
else printf("-1");
return 0;
}
点分树比点分治就多一个记录重心父亲
Day2结束,华丽的分割线