主席树学习记录

来源:互联网 发布:app软件官方下载 编辑:程序博客网 时间:2024/04/29 14:55

搞了一段时间网络流后,最后还是回到了数据结构。。。

主席树,引fotile主席的一段话:

..这个东西是当初我弱不会划分树的时候写出来替代的一个玩意..被一小撮别有用心的人取了很奇怪的名字> <
想法是对原序列的每一个前缀[1..i]建立出一颗线段树维护值域上每个数的出现次数,然后发现这样的树是可以减的,然后就没有然后了

其实是一种比较好理解的数据结构(至少静态查找时是如此),我们对于每个点,建一个类似与前缀和的线段树,然后我们发现这样的n棵线段树是可以相减的,于是。。。但是在实现过程中,由于内存限制的原因,我们一般用指针实现。

COGS 930 找第k小的数。裸题,直接上模板。code:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mid (l+r)/2using 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)/2using 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)/2using 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]);}



 

0 0
原创粉丝点击