主席树-poj2104

来源:互联网 发布:马刺队史数据 编辑:程序博客网 时间:2024/05/23 22:00

邝斌的模板就是好用一打上去就对了,对树状数组也有了初步的了解,主席树相当于N+1课线段树,每颗线段树维护的是数组元素的前缀和或者后缀和,根据映射关系,返回相应的下标,然后取的其值,好吧,初步就是这样,但为什么,邝斌的模板过了,我自己手敲的结构体类型的就 错了,心累,留着吧,以后彻底弄清楚了我再回来解决你。真的服气。

AC代码(邝斌神代码后缀和):

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#define siz 100005#define LL intusing namespace std;int n,q,tot,m;int a[siz],t[siz];int T[siz],lson[siz*30],rson[siz*30],c[siz*30];void Init_hash(){    for(int i=1;i<=n;i++){        t[i]=a[i];    }    sort(t+1,t+1+n);    m=unique(t+1,t+1+n)-t-1;}int build(int l,int r){    int root=tot++;    c[root]=0;    if(l!=r){        int mid=(l+r)>>1;        lson[root]=build(l,mid);        rson[root]=build(mid+1,r);    }    return root;}int hash(int x){    return lower_bound(t+1,t+1+m,x)-t;}int updata(int root,int pos,int val){    int newroot = tot++,tmp=newroot;    c[newroot] = c[root] + val;    int l=1,r=m;    while(l<r){        int mid = (l+r)>>1;        if(pos <= mid){            lson[newroot] = tot++;rson[newroot] = rson[root];            newroot= lson[newroot];root=lson[root];            r=mid;        }        else{            rson[newroot]= tot++;lson[newroot]=lson[root];            newroot=rson[newroot];root=rson[root];            l=mid+1;        }        c[newroot] = c[root]+val;    }    return tmp;}int query(int left_root,int right_root,int k){    int l=1,r=m;    while(l<r){        int mid=(l+r)>>1;        if(c[lson[left_root]]-c[lson[right_root]]>=k){            r=mid;            left_root=lson[left_root];            right_root=lson[right_root];        }        else{            l=mid+1;            k-=c[lson[left_root]]-c[lson[right_root]];            left_root=rson[left_root];            right_root=rson[right_root];        }    }    return l;}void solve(){    tot=0;    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);    }    Init_hash();    //for(int i=1;i<=n;i++){       // cout<<t[i]<<"^^^^"<<endl;   // }   // cout<<m<<"----"<<endl;    T[n+1]=build(1,m);    //cout<<tot<<" "<<m<<endl;    for(int i=n;i>=1;i--){        int pos =hash(a[i]);       // cout<<pos<<endl;        T[i]= updata(T[i+1],pos,1);    }    while(q--){        int l,r,k;        scanf("%d%d%d",&l,&r,&k);        int index=query(T[l],T[r+1],k);        int ans=t[index];        printf("%d\n",ans);    }}int main(){    while(~scanf("%d %d",&n,&q)){        solve();    }    return 0;}

自己很二的过不了的代码:(错误已找到,build里的l我打成了一个1,所以就耗了我一个上午的时间?这么多树,都不好调试。。服了)

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#define siz 100005using namespace std;struct node{    int ls,rs;    int c;}rt[siz*30];int arr[siz],trr[siz],T[siz];int n,q,tot,m;void Init_hash(){    for(int i=1;i<=n;i++){        trr[i]=arr[i];    }    sort(trr+1,trr+n+1);    m=unique(trr+1,trr+1+n)-trr-1;}int build(int l,int r){    int root=tot++;    rt[root].c=0;    if(l!=r){        int mid=(l+r)>>1;        rt[root].ls=build(1,mid);        rt[root].rs=build(mid+1,r);    }    return root;}int hashx(int x){    return lower_bound(trr+1,trr+1+m,x)-trr;}int updata(int root,int pos,int val){    int newroot=tot++,tmp=newroot;    rt[newroot].c=rt[root].c+val;    int l=1,r=m;    while(l<r){        int mid=(l+r)>>1;        if(pos<=mid){            rt[newroot].ls=tot++;            rt[newroot].rs=rt[root].rs;            newroot=rt[newroot].ls;            root=rt[root].ls;            //rt[newroot].c            r=mid;        }        else{            rt[newroot].rs=tot++;            rt[newroot].ls=rt[root].ls;            newroot=rt[newroot].rs;            root=rt[root].rs;            l=mid+1;        }        rt[newroot].c=rt[root].c+val;    }    return tmp;}int query(int left_root,int right_root,int k){    int l=1,r=m;    while(l<r){        int mid=(l+r)>>1;        //int le=        if((rt[rt[left_root].ls].c-rt[rt[right_root].ls].c)>=k){            r=mid;            left_root=rt[left_root].ls;            right_root=rt[right_root].ls;        }        else{            l=mid+1;            k-=(rt[rt[left_root].ls].c-rt[rt[right_root].ls].c);            left_root=rt[left_root].rs;            right_root=rt[right_root].rs;        }    }    return l;}int main(){  int cas;  /// scanf("%d",&cas);  // while(cas--){       while(~scanf("%d %d",&n,&q)){         tot=0;         memset(T,0,sizeof(T));         memset(rt,0,sizeof(rt));        for(int i=1;i<=n;i++){            scanf("%d",&arr[i]);        }        //cout<<"&&"<<endl;        Init_hash();       // cout<<1<<endl;        T[n+1]=build(1,m);        for(int i=n;i>=1;i--){            int pos=hashx(arr[i]);            T[i]=updata(T[i+1],pos,1);        }      /*  for(int i=1;i<=n;i++){            printf("%d ",rt[T[i]].c);        }        cout<<endl;*/        //cout<<1<<endl;        while(q--){            int l,r,k;            scanf("%d %d %d",&l,&r,&k);            int inde=query(T[l],T[r+1],k);            int ans=trr[inde];            printf("%d\n",ans);        }    }    return 0;}

感觉没啥区别呀,就是过不了,就是过不了,真的气!