数据结构——主席树
点击查看代码块
#include <bits/stdc++.h>
#define mkp make_pair
#define pb push_back
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e6+10;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 1e9+7;
const double eps = 1e-7;
int T[maxn<<5];//存储历史版本
int tree[maxn<<5],lc[maxn<<5],rc[maxn<<5];
int n,q;
int a[maxn];
int tot = 0;
int build(int l,int r){
int rt=++tot;
if(l==r){
tree[rt]=a[l];
return rt;
}
int m=(l+r)>>1;
lc[rt]=build(l,m);
rc[rt]=build(m+1,r);
return rt;
}
int update(int pre,int x,int val,int l,int r){
int rt=++tot;
if(l==r){
tree[rt]=val;
return rt;
}
lc[rt]=lc[pre],rc[rt]=rc[pre];
int m=(l+r)>>1;
if(x<=m) lc[rt]=update(lc[pre],x,val,l,m);
else rc[rt]=update(rc[pre],x,val,m+1,r);
return rt;
}
int query(int pre,int x,int l,int r){
if(l==r){
return tree[pre];
}
int m=(l+r)>>1;
if(x<=m) return query(lc[pre],x,l,m);
else return query(rc[pre],x,m+1,r);
}
int main(){
cin>>n>>q;
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
T[0]=build(1,n);
for (int i=1;i<=q;i++){
int v,op;//历史版本,操作
scanf("%d%d",&v,&op);
if(op == 1){
int x,y;
scanf("%d%d",&x,&y);
T[i]=update(T[v],x,y,1,n);
}
else if(op == 2){
int x;
scanf("%d",&x);
T[i]=T[v];
int ans = query(T[v],x,1,n);
printf("%d\n",ans);
}
}
return 0;
}
点击查看代码块
#include <bits/stdc++.h>
#define mkp make_pair
#define pb push_back
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2e5+10;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 1e9+7;
const double eps = 1e-7;
int n,m;
ll tree[maxn<<5],lc[maxn<<5],rc[maxn<<5];
ll T[maxn];
ll tot = 0;//当前节点编号
ll a[maxn],b[maxn];//a原数组,b离散化数组
int build(int l,int r){
int rt = ++tot;
tree[rt] = 0;
if(l==r){
return rt;
}
int m=(l+r)>>1;
lc[rt]=build(l,m);
rc[rt]=build(m+1,r);
return rt;
}
int update(int pre,int x,int l,int r){
int rt = ++tot;
if(l == r){
tree[rt]=tree[pre]+1;
return rt;
}
lc[rt]=lc[pre];rc[rt]=rc[pre];tree[rt]=tree[pre]+1;
int m=(l+r)>>1;
if(x<=m) lc[rt]=update(lc[pre],x,l,m);
else rc[rt]=update(rc[pre],x,m+1,r);
return rt;
}
int query(int u,int v,int l,int r,int k){
if(l==r) return l;
int x=tree[lc[v]]-tree[lc[u]];//前缀值相减
int m=(l+r)>>1;
if(x>=k) return query(lc[u],lc[v],l,m,k);
else return query(rc[u],rc[v],m+1,r,k-x);//注意这里的k变为k-x
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%lld",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
int cnt = unique(b+1,b+n+1)-b-1;
T[0] = build(1,cnt);
for (int i=1;i<=n;i++){
int pos = lower_bound(b+1,b+cnt+1,a[i])-b;
T[i]=update(T[i-1],pos,1,cnt);
}
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int pos = query(T[x-1],T[y],1,cnt,z);
printf("%lld\n",b[pos]);
}
return 0;
}
3.P2633 Count on a tree
主席树+树上差分
点击查看代码块
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn = 1e5+10;
int n,m;
int a[maxn],b[maxn];
vector<int> G[maxn];
int fa[maxn][35];
int dep[maxn];
int tot;//离散化
void dfs(int u,int f){
dep[u] = dep[f] + 1;
fa[u][0] = f;
for (int i=1;(1<<i)<=dep[u];i++){
fa[u][i] = fa[fa[u][i-1]][i-1];
}
for (auto v : G[u]){
if( v==f ) continue;
dfs(v,u);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for (int i=30;i>=0;i--){
int d = dep[u]-dep[v];
if(d>=(1<<i)) u = fa[u][i];
}
if(u==v) return u;
for (int i=30;i>=0;i--){
if(fa[u][i]!=fa[v][i]){
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
int id[maxn],cnt = 0;
int num[maxn<<5],lc[maxn<<5],rc[maxn<<5];
void pushup(int p){
num[p] = num[lc[p]] + num[rc[p]];
}
int update(int pre,int l,int r,int pos,int val){
int p = ++cnt;
lc[p]=lc[pre],rc[p]=rc[pre],num[p]=num[pre];
if(l == r){
num[p]+=val;
return p;
}
int m = (l+r)>>1;
if(pos <= m) lc[p]=update(lc[pre],l,m,pos,val);
else rc[p]=update(rc[pre],m+1,r,pos,val);
pushup(p);
return p;
}
int query(int aa,int bb,int cc,int dd,int l,int r,int k){
if(l == r) return b[l];
int x = num[lc[aa]]+num[lc[bb]]-num[lc[cc]]-num[lc[dd]];
int m = (l+r)>>1;
if(x >= k) return query(lc[aa],lc[bb],lc[cc],lc[dd],l,m,k);
else return query(rc[aa],rc[bb],rc[cc],rc[dd],m+1,r,k-x);
}
void dfs2(int u,int f){
int pos = lower_bound(b+1,b+tot+1,a[u])-b;
id[u] = update(id[f],1,tot,pos,1);
for (auto v : G[u]){
if(v == f) continue;
dfs2(v,u);
}
}
int main(){
cin>>n>>m;
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i] = a[i];
}
sort(b+1,b+n+1);
tot = unique(b+1,b+n+1)-b-1;
for (int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
dfs2(1,0);
int last = 0;
for (int i=1;i<=m;i++){
int u,v,k;
scanf("%d%d%d",&u,&v,&k);
u^=last;
int Lca = lca(u,v),f = fa[Lca][0];
int ans = query(id[u],id[v],id[Lca],id[f],1,tot,k);
printf("%d\n",ans);
last = ans;
}
return 0;
}