搞了一段时间网络流后,最后还是回到了数据结构。。。
主席树,引fotile主席的一段话:
..这个东西是当初我弱不会划分树的时候写出来替代的一个玩意..被一小撮别有用心的人取了很奇怪的名字> <
想法是对原序列的每一个前缀[1..i]建立出一颗线段树维护值域上每个数的出现次数,然后发现这样的树是可以减的,然后就没有然后了
其实是一种比较好理解的数据结构(至少静态查找时是如此),我们对于每个点,建一个类似与前缀和的线段树,然后我们发现这样的n棵线段树是可以相减的,于是。。。但是在实现过程中,由于内存限制的原因,我们一般用指针实现。
COGS 930 找第k小的数。裸题,直接上模板。code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid (l+r)/2 using namespace std; struct node{ node *left,*right; int a,size; node(){left=right=NULL; size=a=0;} int updata() { size=a; if (left) size+=left->size; if (right) size+=right->size; } }*null=new node(),*root[100001]={NULL},q[2000001]; int n,m,a[100001],b[100001]; int temp,ans; void build(node *&y,node *&x,int l,int r,int t) { if (x==NULL) x=null; y=&q[++temp]; *y=node(); if (l==r) { *y=*x; y->size++; y->a++; return; } if (t<=b[mid]) { build(y->left,x->left,l,mid,t); y->right=x->right; y->updata(); } else { build(y->right,x->right,mid+1,r,t); y->left=x->left; y->updata(); } } void find(node *x1,node *x2,int l,int r,int k) { int ls; if (x1==NULL) x1=null; if (x2==NULL) x2=null; ls=0; if (l==r) {ans=b[l]; return;} if (x2->left) ls+=x2->left->size; if (x1->left) ls-=x1->left->size; if (ls>=k) find(x1->left,x2->left,l,mid,k); else find(x1->right,x2->right,mid+1,r,k-ls); } int main() { int i,size,x,l,r,k; freopen("kth.in","r",stdin); freopen("kth.out","w",stdout); scanf("%d%d",&n,&m); null->left=null; null->right=null; for (i=1;i<=n;++i) { scanf("%d",&a[i]); b[i]=a[i]; } sort(b+1,b+n+1); size=unique(b+1,b+n+1)-b-1; temp=0; for (i=1;i<=n;++i) build(root[i],root[i-1],1,size,a[i]); for (i=1;i<=m;++i) { scanf("%d%d%d",&l,&r,&k); ans=0; find(root[l-1],root[r],1,size,k); printf("%d\n",ans); } fclose(stdin); fclose(stdout); }
动态主席树,其实救是树状数组套线段树,COGS 257 动态排名系统 code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid (l+r)/2 using namespace std; struct hp{ int size,l,r; }tree[10000001]; struct hq{ char op; int x,y,k; }qst[10001]; int t,n,m,tot,size; int root[50001],a[50001],b[60001],q1[2000],q2[2000]; int lowbit(int x) {return x&(-x); } void build(int &x,int l,int r) { tree[x=++tot].size=0; if (l==r) return; build(tree[x].l,l,mid); build(tree[x].r,mid+1,r); } void insert(int last,int &i,int l,int r,int x,int flag) { tree[i=++tot].size=tree[last].size+flag; tree[i].l=tree[last].l; tree[i].r=tree[last].r; if (l==r) return; if (x<=mid) insert(tree[last].l,tree[i].l,l,mid,x,flag); else insert(tree[last].r,tree[i].r,mid+1,r,x,flag); } void bit_ins(int i,int x,int flag) { for (;i<=n;i+=lowbit(i)) insert(root[i],root[i],1,size,x,flag); } int ask(int l,int r,int k) { int ss=0,i; if (l==r) return l; for (i=1;i<=q2[0];++i) ss+=tree[tree[q2[i]].l].size; for (i=1;i<=q1[0];++i) ss-=tree[tree[q1[i]].l].size; if (k<=ss) { for (i=1;i<=q2[0];++i) q2[i]=tree[q2[i]].l; for (i=1;i<=q1[0];++i) q1[i]=tree[q1[i]].l; return ask(l,mid,k); } else { for (i=1;i<=q2[0];++i) q2[i]=tree[q2[i]].r; for (i=1;i<=q1[0];++i) q1[i]=tree[q1[i]].r; return ask(mid+1,r,k-ss); } } int bit_ask(int l,int r,int k) { q2[0]=q1[0]=0; for (;r;r-=lowbit(r)) q2[++q2[0]]=root[r]; for (;l;l-=lowbit(l)) q1[++q1[0]]=root[l]; return ask(1,size,k); } int main() { int i,j; freopen("dynrank.in","r",stdin); freopen("dynrank.out","w",stdout); scanf("%d",&t); while (t) { memset(root,0,sizeof(root)); memset(tree,0,sizeof(tree)); tot=0; b[0]=0; scanf("%d%d",&n,&m); for (i=1;i<=n;++i) { scanf("%d",&a[i]); b[0]++;b[b[0]]=a[i]; } for (i=1;i<=m;++i) { scanf("%*c%c",&qst[i].op); if (qst[i].op=='Q') scanf("%d%d%d",&qst[i].x,&qst[i].y,&qst[i].k); else { scanf("%d%d",&qst[i].x,&qst[i].k); b[0]++; b[b[0]]=qst[i].k; } } sort(b+1,b+b[0]+1); size=unique(b+1,b+b[0]+1)-b-1; build(root[0],1,size); for (i=1;i<=n;++i) { a[i]=upper_bound(b+1,b+size+1,a[i])-b-1; bit_ins(i,a[i],1); } for (i=1;i<=m;++i) { if (qst[i].op=='Q') { j=bit_ask(qst[i].x-1,qst[i].y,qst[i].k); printf("%d\n",b[j]); } else { bit_ins(qst[i].x,a[qst[i].x],-1); a[qst[i].x]=upper_bound(b+1,b+size+1,qst[i].k)-b-1; bit_ins(qst[i].x,a[qst[i].x],1); } } t--; } fclose(stdin); fclose(stdout); }
其实稍微转化一下就成模板题啦~~ code:
#include<iostream> #include<cstdio> #include<cstring> #define mid (l+r)/2 using namespace std; struct hp{ int size,l,r; }tree[10000000]; int root[100001],q1[2000],q2[2000],n,m; int a[100001],a2[100001],c[100001],pos[100001],tot,del[100001]; long long ansi[50001]={0}; int lowbit(int x) { return x&(-x); } long long work(int l,int r) { int i,j; int ans=0; if (l==r) return ans; ans+=work(l,mid)+work(mid+1,r); i=l; j=mid+1; c[0]=0; while (i<=mid&&j<=r) { if (a2[i]<a2[j]) { c[++c[0]]=a2[i]; i++; } else { c[++c[0]]=a2[j]; j++; ans+=mid-i+1; } } for (;i<=mid;++i) c[++c[0]]=a2[i]; for (;j<=r;++j) c[++c[0]]=a2[j]; for (i=l;i<=r;++i) a2[i]=c[i-l+1]; return ans; } void build(int &x,int l,int r) { tree[x=++tot].size=0; if (l==r) return; build(tree[x].l,l,mid); build(tree[x].r,mid+1,r); } long long askless(int l,int r,int x) { int ss=0; int i; if (l==r) return 0; for (i=1;i<=q2[0];++i) ss+=tree[tree[q2[i]].l].size; for (i=1;i<=q1[0];++i) ss-=tree[tree[q1[i]].l].size; if (x<=mid) { for (i=1;i<=q2[0];++i) q2[i]=tree[q2[i]].l; for (i=1;i<=q1[0];++i) q1[i]=tree[q1[i]].l; return askless(l,mid,x); } else { for (i=1;i<=q2[0];++i) q2[i]=tree[q2[i]].r; for (i=1;i<=q1[0];++i) q1[i]=tree[q1[i]].r; return ss+askless(mid+1,r,x); } } long long askmore(int l,int r,int x) { int ss=0; int i; if (l==r) return 0; for (i=1;i<=q2[0];++i) ss+=tree[tree[q2[i]].r].size; for (i=1;i<=q1[0];++i) ss-=tree[tree[q1[i]].r].size; if (x>mid) { for (i=1;i<=q2[0];++i) q2[i]=tree[q2[i]].r; for (i=1;i<=q1[0];++i) q1[i]=tree[q1[i]].r; return askmore(mid+1,r,x); } else { for (i=1;i<=q2[0];++i) q2[i]=tree[q2[i]].l; for (i=1;i<=q1[0];++i) q1[i]=tree[q1[i]].l; return ss+askmore(l,mid,x); } } long long bit_askless(int l,int r,int x) { q1[0]=q2[0]=0; for (;l;l-=lowbit(l)) q1[++q1[0]]=root[l]; for (;r;r-=lowbit(r)) q2[++q2[0]]=root[r]; askless(1,n,x); } long long bit_askmore(int l,int r,int x) { q1[0]=q2[0]=0; for (;l;l-=lowbit(l)) q1[++q1[0]]=root[l]; for (;r;r-=lowbit(r)) q2[++q2[0]]=root[r]; askmore(1,n,x); } void insert(int last,int &i,int l,int r,int x,int flag) { if (!i) i=++tot; tree[i].size=tree[last].size+flag; tree[i].l=tree[last].l; tree[i].r=tree[last].r; if (l==r) return; if (x<=mid) insert(tree[last].l,tree[i].l,l,mid,x,flag); else insert(tree[last].r,tree[i].r,mid+1,r,x,flag); } void bit_ins(int i,int x,int flag) { for (;i<=n;i+=lowbit(i)) insert(root[i],root[i],1,n,x,flag); } int main() { int i; long long ans=0; scanf("%d%d",&n,&m); tot=0; for (i=1;i<=n;++i) { scanf("%d",&a[i]); pos[a[i]]=i; } for (i=1;i<=m;++i) { scanf("%d",&del[i]); a[pos[del[i]]]=0; } build(root[0],1,n); for (i=1;i<=n;++i) if (a[i]) { bit_ins(i,a[i],1); a2[++a2[0]]=a[i]; } ans=work(1,a2[0]); for (i=m;i>=1;--i) { bit_ins(pos[del[i]],del[i],1); if (pos[del[i]]>1) ans+=bit_askmore(0,pos[del[i]]-1,del[i]); if (pos[del[i]]<n) ans+=bit_askless(pos[del[i]],n,del[i]); ansi[i]=ans; } for (i=1;i<=m;++i) printf("%lld\n",ansi[i]); }