FHQ-Treap
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct Node
{
int l,r;
int val,key;
int size;
}tr[N];
int root,idx,n;
int add(int key)
{
tr[++idx].val = rand(),tr[idx].key = key,tr[idx].size = 1;
return idx;
}
void pushup(int u)
{
tr[u].size = tr[tr[u].l].size + tr[tr[u].r].size + 1;
}
void split(int u,int key,int &x,int &y)
{
if(!u) return x = y = 0,void();
if(tr[u].key <= key) x = u,split(tr[u].r,key,tr[u].r,y);
else y = u,split(tr[u].l,key,x,tr[u].l);
pushup(u);
}
int merge(int x,int y)
{
if(!x||!y) return x + y;
if(tr[x].val > tr[y].val)
{
tr[x].r = merge(tr[x].r,y);
pushup(x);
return x;
}
tr[y].l = merge(x,tr[y].l);
pushup(y);
return y;
}
void insert(int key)
{
int x,y;
split(root,key,x,y);
root = merge(x,merge(add(key),y));
}
void remove(int key)
{
int x,y,z;
split(root,key,x,z);
split(x,key-1,x,y);
y = merge(tr[y].l,tr[y].r);
root = merge(merge(x,y),z);
}
int get_rank_by_key(int key)
{
int x,y;
split(root,key-1,x,y);
int res = tr[x].size + 1;
root = merge(x,y);
return res;
}
int get_key_by_rank(int k)
{
int u = root;
while(u)
{
if(tr[tr[u].l].size + 1 == k) return tr[u].key;
if(tr[tr[u].l].size >= k ) u = tr[u].l;
else k-= tr[tr[u].l].size + 1,u = tr[u].r;
}
return -1;
}
int get_prev(int key)
{
int x,y;
split(root,key-1,x,y);
int u = x;
while(tr[u].r) u = tr[u].r;
int res = tr[u].key;
root = merge(x,y);
return res;
}
int get_next(int key)
{
int x,y;
split(root,key,x,y);
int u = y;
while(tr[u].l) u = tr[u].l;
int res = tr[u].key;
root = merge(x,y);
return res;
}
int main()
{
scanf("%d",&n);
while(n--)
{
int opt,x;
scanf("%d%d",&opt,&x);
if(opt==1) insert(x);
else if(opt==2) remove(x);
else if(opt==3) printf("%d\n",get_rank_by_key(x));
else if(opt==4) printf("%d\n",get_key_by_rank(x));
else if(opt==5) printf("%d\n",get_prev(x));
else printf("%d\n",get_next(x));
}
return 0;
}
Splay
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct Node
{
int s[2],p,v;
int size,flag;
void init(int _p,int _v)
{
p = _p;
v = _v;
size = 1;
}
}tr[N];
int root,idx;
int n,m;
void pushup(int x)
{
tr[x].size = tr[tr[x].s[0]].size + tr[tr[x].s[1]].size + 1;
}
void pushdown(int x)
{
if(tr[x].flag)
{
swap(tr[x].s[0],tr[x].s[1]);
tr[tr[x].s[0]].flag ^= 1;
tr[tr[x].s[1]].flag ^= 1;
tr[x].flag = 0;
}
}
void rotate(int x)
{
int y = tr[x].p,z = tr[y].p;
int k = tr[y].s[1] == x;
tr[z].s[tr[z].s[1] == y] = x,tr[x].p = z;
tr[y].s[k] = tr[x].s[k^1], tr[tr[x].s[k^1]].p = y;
tr[x].s[k^1] = y,tr[y].p = x;
pushup(y),pushup(x);
}
void splay(int x,int k)
{
while(tr[x].p != k)
{
int y = tr[x].p,z = tr[y].p;
if(z!=k)
{
if((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
if(!k) root = x;
}
void insert(int v)
{
int u = root,p = 0;
while(u) p = u,u = tr[u].s[v > tr[u].v];
u = ++idx;
if(p) tr[p].s[v > tr[p].v] = u;
tr[u].init(p,v);
splay(u,0);
}
int get_k(int k)
{
int u = root;
while(true)
{
pushdown(u);
if(tr[tr[u].s[0]].size >= k) u = tr[u].s[0];
else if(tr[tr[u].s[0]].size + 1 == k) return u;
else k -= tr[tr[u].s[0]].size + 1,u = tr[u].s[1];
pushup(u);
}
return -1;
}
void output(int u)
{
pushdown(u);
if(tr[u].s[0]) output(tr[u].s[0]);
if(tr[u].v >= 1 && tr[u].v <= n) printf("%d ",tr[u].v);
if(tr[u].s[1]) output(tr[u].s[1]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 0;i<=n+1;i++) insert(i);
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
l = get_k(l),r = get_k(r+2);
splay(l,0),splay(r,l);
tr[tr[r].s[0]].flag ^= 1;
}
output(root);
return 0;
}
可持久化线段树(主席树)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
struct Node
{
int l,r;
int cnt;
}tr[4*N + 17*N];
int root[N],idx,a[N];
int n,m;
vector<int> v;
int find(int x)
{
return lower_bound(v.begin(),v.end(),x) - v.begin();
}
int build(int l,int r)
{
int p = ++idx;
if(l==r) return p;
int mid = l + r >> 1;
tr[p].l = build(l,mid),tr[p].r = build(mid+1,r);
return p;
}
int insert(int p,int l,int r,int x)
{
int q = ++idx;
tr[q] = tr[p];
if(l==r)
{
tr[q].cnt++;
return q;
}
int mid = l + r >> 1;
if(x<=mid) tr[q].l = insert(tr[p].l,l,mid,x);
else tr[q].r = insert(tr[p].r,mid+1,r,x);
tr[q].cnt= tr[tr[q].l].cnt + tr[tr[q].r].cnt;
return q;
}
int query(int q,int p,int l,int r,int k)
{
if(l==r) return r;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int mid = l + r >> 1;
if(cnt>=k) return query(tr[q].l,tr[p].l,l,mid,k);
else return query(tr[q].r,tr[p].r,mid+1,r,k-cnt);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i<=n;i++)
{
scanf("%d",&a[i]);
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
root[0] = build(0,v.size()-1);
for(int i = 1;i<=n;i++)
{
root[i] = insert(root[i-1],0,v.size()-1,find(a[i]));
}
while(m--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",v[query(root[r],root[l-1],0,v.size()-1,k)]);
}
return 0;
}
AC自动机
using namespace std;
const int N = 2e5+10,M = 2e6+10;
int tr[N][26],id[N],ne[N],tot,Size[N],cnt[N];
int q[N];
char str[M];
int h[N],e[N],Ne[N],n,idx;
void add(int a,int b)
{
e[idx] = b,Ne[idx] = h[a],h[a] = idx++;
}
void insert(int x)
{
int p = 0;
for(int i = 0;str[i];i++)
{
int t = str[i] - 'a';
if(!tr[p][t]) tr[p][t] = ++tot;
p = tr[p][t];
}
id[x] = p;
}
void build()
{
int tt = -1,hh = 0;
for(int i = 0;i<26;i++) if(tr[0][i]) q[++tt] = tr[0][i];
while(tt>=hh)
{
int t = q[hh++];
for(int i = 0;i<26;i++)
{
int &p = tr[t][i];
if(!p) p = tr[ne[t]][i];
else
{
ne[p] = tr[ne[t]][i];
q[++tt] = p;
}
}
}
}
void dfs(int u)
{
for(int i = h[u];~i;i=Ne[i])
{
int j = e[i];
dfs(j);
Size[u] += Size[j];
}
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d",&n);
for(int i = 0;i<n;i++) scanf("%s",str),insert(i);
build();
scanf("%s",str);
for(int i = 0,j = 0;str[i];i++)
{
int t = str[i] - 'a';
j = tr[j][t];
Size[j]++;
}
for(int i = 1;i<=tot;i++) add(ne[i],i);
dfs(0);
for(int i = 0;i<n;i++) printf("%d\n",Size[id[i]]);
return 0;
}
线段树
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架