可持久化线段树模板
#include<cstdio> #include<vector> #include<algorithm> #define N 100007 using namespace std; struct arr{ int ls,rs,cnt; }tr[N*20]; vector<int> s; int n,m,a[N],tot,root[N]; int find(int x){ return lower_bound(s.begin(),s.end(),x)-s.begin(); } int build(int l,int r){ int p=++tot,mid=(l+r)/2; if (l==r) return p; tr[p].ls=build(l,mid); tr[p].rs=build(mid+1,r); return p; } int inse(int p,int l,int r,int x){ int q=++tot,mid=(l+r)/2; tr[q].ls=tr[p].ls,tr[q].rs=tr[p].rs; if (l==r){ tr[q].cnt++; return q; } if (x<=mid) tr[q].ls=inse(tr[p].ls,l,mid,x); else tr[q].rs=inse(tr[p].rs,mid+1,r,x); tr[q].cnt=tr[tr[q].ls].cnt+tr[tr[q].rs].cnt; return q; } int que(int p,int q,int l,int r,int k){ int mid=(l+r)/2,c; if (l==r) return l; c=tr[tr[q].ls].cnt-tr[tr[p].ls].cnt; if (c>=k) return que(tr[p].ls,tr[q].ls,l,mid,k); return que(tr[p].rs,tr[q].rs,mid+1,r,k-c); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); s.push_back(a[i]); } sort(s.begin(),s.end()); s.erase(unique(s.begin(),s.end()),s.end()); root[0]=build(0,s.size()-1); for (int i=1;i<=n;i++) root[i]=inse(root[i-1],0,s.size()-1,find(a[i])); for (int i=1;i<=m;i++){ int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d ",s[que(root[l-1],root[r],0,s.size()-1,k)]); } }
treap模板
#include<cstdio> #include<algorithm> #define N 1000007 #define INF 1e8 using namespace std; struct arr{ int ls,rs,key,val,cnt,size; }tr[N]; int tot,root,n; int getnode(int key){ tr[++tot].key=key; srand(tot); tr[tot].val=rand(); tr[tot].cnt=tr[tot].size=1; return tot; } void renew(int p){ tr[p].size=tr[tr[p].ls].size+tr[tr[p].rs].size+tr[p].cnt; } void zuo(int &p){ int q=tr[p].rs; tr[p].rs=tr[q].ls; tr[q].ls=p; p=q; renew(tr[p].ls),renew(p); } void you(int &p){ int q=tr[p].ls; tr[p].ls=tr[q].rs; tr[q].rs=p; p=q; renew(tr[p].rs),renew(p); } void build(){ getnode(-INF),getnode(INF); root=1,tr[1].rs=2; if (tr[1].val<tr[2].val) zuo(root); } void add(int &p,int key){ if (!p){ p=getnode(key); return; } if (tr[p].key==key) tr[p].cnt++; if (tr[p].key<key){ add(tr[p].rs,key); if (tr[tr[p].rs].val>tr[p].val) zuo(p); } if (tr[p].key>key){ add(tr[p].ls,key); if (tr[tr[p].ls].val>tr[p].val) you(p); } renew(p); } void del(int &p,int key){ if (!p) return; if (tr[p].key==key) if (tr[p].cnt>1) tr[p].cnt--; else if (tr[p].ls||tr[p].rs) if (!tr[p].rs||tr[tr[p].ls].val>tr[tr[p].rs].val){ you(p); del(tr[p].rs,key); } else{ zuo(p); del(tr[p].ls,key); } else p=0; else if (tr[p].key>key) del(tr[p].ls,key); else del(tr[p].rs,key); renew(p); } int find1(int p,int key){ if (!p) return 0; if (tr[p].key==key) return tr[tr[p].ls].size+1; if (tr[p].key>key) return find1(tr[p].ls,key); return tr[tr[p].ls].size+tr[p].cnt+find1(tr[p].rs,key); } int find2(int p,int rank){ if (!p) return INF; if (tr[tr[p].ls].size>=rank) return find2(tr[p].ls,rank); if (tr[tr[p].ls].size+tr[p].cnt>=rank) return tr[p].key; return find2(tr[p].rs,rank-tr[tr[p].ls].size-tr[p].cnt); } int pre(int p,int x){ if (!p) return -INF; if (tr[p].key>=x) return pre(tr[p].ls,x); return max(tr[p].key,pre(tr[p].rs,x)); } int last(int p,int x){ if (!p) return INF; if (tr[p].key<=x) return last(tr[p].rs,x); return min(tr[p].key,last(tr[p].ls,x)); } int main(){ scanf("%d",&n); build(); for (int i=1;i<=n;i++){ int opt,x; scanf("%d%d",&opt,&x); if (opt==1) add(root,x); if (opt==2) del(root,x); if (opt==3) printf("%d ",find1(root,x)-1); if (opt==4) printf("%d ",find2(root,x+1)); if (opt==5) printf("%d ",pre(root,x)); if (opt==6) printf("%d ",last(root,x)); } }
ac自动机模板
#include<cstdio> #include<queue> #include<cstring> #define N 10001 #define M 1000001 #define S 51 using namespace std; int ans,tot,n,t,cnt[N*S],tr[N*S][26],ne[N*S]; char s[M]; void add(){ int p=0; for (int i=0;s[i]!='