HDU4417-主席树-划分树-树状数组-分块-线段树-归并树-总结

题目:传送门

给你一段长为n序列,m次询问,询问[L,R]区间内小于等于H的数有多少个。
数据范围,n,m<=1e5

结果:

树状数组: 249ms
主席树: 218ms
归并树: 374ms
分块:C++TLE / G++AC –(不过C++把块的大小扩大3倍也能过)
归并树: TLE
线段树: WA (求大佬找下bug,我真不知道为什么会wa,感觉对如闪电

(TLE和WA一定是我太垃圾,写残了,orz)

代码如下:

线段树:WA

#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define lsonl rt<<1,l,m
#define rsonr rt<<1|1,m+1,r
using namespace std;
typedef long long LL;
const int N = 1e5+5;
int n,m,Ans[N];
struct lp{
    int l,r,sum;
}cw[N<<2];
struct lh{
    int val,id,l,r;
    bool operator <(const lh a)const{
        return val<a.val;
    }
}ar[N],br[N];
void build(int rt,int l,int r){
    cw[rt].l=l;cw[rt].r=r;cw[rt].sum=0;
    int mid=(l+r)>>1;
    if(l==r)return;
    build(lson,l,mid);
    build(rson,mid+1,r);
}
void update(int rt,int x){
    cw[rt].sum++;
    if(cw[rt].l==cw[rt].r){
        return;
    }
    int m=(cw[rt].l+cw[rt].r)/2;
    if(x<=m)update(lson,x);
    else update(rson,x);
}
int query(int rt,int l,int r){
    if(l=cw[rt].l&&cw[rt].r==r){
        return cw[rt].sum;
    }
    int m=(cw[rt].l+cw[rt].r)>>1;
    if(l>m) return query(rson,l,r);
    else if(r<=m) return query(lson,l,r);
    else{
        return query(lsonl)+query(rsonr);
    }
}
int main(){
    int tim;
    int T=0;
    scanf("%d",&tim);
    while(tim--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i){
            scanf("%d",&ar[i].val);
            ar[i].id=i+1;
        }
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&br[i].l,&br[i].r,&br[i].val);
            br[i].id=i;
        }
        sort(ar,ar+n);
        sort(br,br+m);
        build(1,1,n);
        printf("Case %d:\n",++T );
        for(int i=0,j=0;i<m;++i){
            while(j<n&&ar[j].val<=br[i].val){
                update(1,ar[j].id);
                j++;
            }
            Ans[br[i].id]=query(1,br[i].l+1,br[i].r+1);
        }
        for(int i=0;i<m;++i){
            printf("%d\n",Ans[i] );
        }
    }
    return 0;
}


分块:AC。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6+5;
int n,m;
int block,num,belong[N],ls[N],rs[N];
int ar[N];
vector<int>bk[N];
void build(){
    block=3*sqrt(n*1.0);
    num=n/block;if(n%block)num++;
    for(int i=1;i<=n;++i){
        belong[i]=(i-1)/block+1;
    }
    for(int i=1;i<=num;++i){
        ls[i]=(i-1)*block+1;
        rs[i]=i*block;
    }
    rs[num]=n;
    for(int i=0;i<=num;++i)bk[i].clear();
    for(int i=1;i<=n;++i){
        bk[belong[i]].push_back(ar[i]);
    }
    for(int i=1;i<=num;++i){
        sort(bk[i].begin(),bk[i].end());
    }
}
void get(int u,int v,int w){
    int cnt=0;
    if(belong[u]==belong[v]){
        for(int i=u;i<=v;++i){
            if(ar[i]<=w)cnt++;
        }
        printf("%d\n",cnt );
        return;
    }
    for(int i=belong[u]+1;i<belong[v];++i){
        int p=upper_bound(bk[i].begin(),bk[i].end(),w)-bk[i].begin();
        cnt+=(p<0?0:p);
    }
    if(u==ls[belong[u]]){
        int i=belong[u];
        int p=upper_bound(bk[i].begin(),bk[i].end(),w)-bk[i].begin();
        cnt+=(p<0?0:p);     
    }else{
        for(int i=u;i<=rs[belong[u]];++i){
            if(ar[i]<=w)cnt++;
        }
    }
    if(v==rs[belong[v]]){
        int i=belong[v];
        int p=upper_bound(bk[i].begin(),bk[i].end(),w)-bk[i].begin();
        cnt+=(p<0?0:p);
    }else{
        for(int i=ls[belong[v]];i<=v;++i){
            if(ar[i]<=w)cnt++;
        }
    }
    printf("%d\n",cnt );
}
int main(){
    int tim;scanf("%d",&tim);
    int T=0;
    while(tim--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&ar[i]);
        }
        build();
        printf("Case %d:\n",++T );
        for(int i=0,u,v,w;i<m;++i){
            scanf("%d%d%d",&u,&v,&w);
            get(u+1,v+1,w);
        }
    }
    return 0;
}


归并树:TLE

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
int n,m;
int cw[20][N];
int ar[N];
void build(int dep,int l,int r){
    if(l==r){
        cw[dep][l]=ar[l];
        return;
    }
    int mid=(l+r)>>1;
    build(dep+1,l,mid);
    build(dep+1,mid+1,r);
    int i=l,j=mid+1,k=l;
    while(i<=mid||j<=r){
        if(j>r||(i<=mid&&cw[dep+1][i]<=cw[dep+1][j])){
            cw[dep][k++]=cw[dep+1][i++];
        }else{
            cw[dep][k++]=cw[dep+1][j++];
        }
    }
}
int query(int dep,int l,int r,int L,int R,int key){
    if(L>r||R<l)return 0;
    if(L<=l&&r<=R){
        return lower_bound(&cw[dep][l],&cw[dep][r]+1,key)-&cw[dep][l];
    }
    int mid=(l+r)>>1;
    return query(dep+1,l,mid,L,R,key)+query(dep+1,mid+1,r,L,R,key);
}
int solve(int n,int L,int R,int k){
    int l=1,r=n,ans=1,mid;
    while(l<=r){
        mid=(l+r)>>1;
        int cnt=query(0,1,n,L,R,cw[0][mid]);
        if(cnt>k){
            r=mid-1;
            ans=mid-1;
        }else{
            ans=mid;
            l=mid+1;
        }
    }
    return cw[0][ans];
}
int main(){
    int tim,T=0;
    scanf("%d",&tim);
    while(tim--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&ar[i]);
        }
        build(0,1,n);
        printf("Case %d:\n",++T );
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            x++;y++;
            int l=1,r=y-x+1,mid,ans=0,tmp;
            while(l<=r){
                mid=(l+r)>>1;
                tmp=solve(n,x,y,mid-1);
                if(tmp<=z){
                    l=mid+1;
                    ans=mid;
                }else{
                    r=mid-1;
                    ans=mid-1;
                }
            }
            printf("%d\n",ans );
        }
    }
    return 0;
}


树状数组: AC

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int N = 1e5+5;
int n,m;
int ar[N],sum[N];
inline int lowbit(int x){
    return x&(-x);
}
inline void add(int x,int d){
    while(x<=n){
        ar[x]+=d;
        x+=lowbit(x);
    }
}
inline int query(int x){
    int ans=0;
    while(x){
        ans+=ar[x];
        x-=lowbit(x);
    }
    return ans;
}
struct lh{
    int val,id;
}br[N];
bool cmp1(lh &a,lh &b){
    if(a.val!=b.val)return a.val<b.val;
    return a.id<b.id;
}
struct lp{
    int l,r,id,val;
}cw[N];
bool cmp2(lp &a,lp &b){
    if(a.val!=b.val)return a.val<b.val;
    return a.id<b.id;
}
int main(){
    int tim;scanf("%d",&tim);
    int T=0;
    while(tim--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i){
            scanf("%d",&br[i].val);
            br[i].id=i+1;
        }
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&cw[i].l,&cw[i].r,&cw[i].val);
            cw[i].l++;cw[i].r++;
            cw[i].id=i+1;
        }
        sort(br,br+n,cmp1);
        sort(cw,cw+m,cmp2);
        memset(ar,0,sizeof(ar));
        for(int i=0,j=0;i<m;++i){
            while(j<n&&br[j].val<=cw[i].val){
                add(br[j].id,1);
                j++;
            }
            sum[cw[i].id]=query(cw[i].r)-query(cw[i].l-1);
        }
        printf("Case %d:\n",++T );
        for(int i=1;i<=m;++i){
            printf("%d\n",sum[i] );
        }
    }
    return 0;
}


主席树: AC

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6+5;
int n,m;
struct lp{
    int l,r,sum;
}cw[N*20];
int rak[N],ar[N],br[N],tot;
void update(int l,int r,int last,int &cur,int x){
    cw[++tot]=cw[last];
    cw[tot].sum++;
    cur=tot;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(x<=mid)update(l,mid,cw[last].l,cw[cur].l,x);
    else update(mid+1,r,cw[last].r,cw[cur].r,x);
}
int query(int l,int r,int last,int cur,int k){
    if(l==r)return cw[cur].sum-cw[last].sum;
    int mid=(l+r)>>1;
    if(k<=mid)return query(l,mid,cw[last].l,cw[cur].l,k);
    else {
        int ans=query(mid+1,r,cw[last].r,cw[cur].r,k);
        ans+=cw[cw[cur].l].sum-cw[cw[last].l].sum;
        return ans;
    }
}
int main(){
    int tim;scanf("%d",&tim);
    int T=0;
    while(tim--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&ar[i]);
            br[i]=ar[i];
        }
        sort(br+1,br+1+n);
        int k=1;
        for(int i=2;i<=n;++i){
            if(br[i]!=br[i-1]){
                br[++k]=br[i];
            }
        }
        tot=0;cw[0].l=cw[0].r=cw[0].sum=0;
        memset(rak,0,sizeof(rak));
        for(int i=1;i<=n;++i){
            int p=lower_bound(br+1,br+1+k,ar[i])-br;
            update(1,k,rak[i-1],rak[i],p);
        }
        printf("Case %d:\n",++T );
        for(int i=0,u,v,w;i<m;++i){
            scanf("%d%d%d",&u,&v,&w);
            u++;v++;
            int p=upper_bound(br+1,br+1+k,w)-br-1;
            if(p)printf("%d\n",query(1,k,rak[u-1],rak[v],p) );
            else printf("0\n");
        }
    }
    return 0;
}


划分树:AC

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
int n,m,sor[N];
struct lp{
    int cnt[N];
    int num[N];
}cw[22];
void build(int l,int r,int d){
    if(l==r)return;
    cw[d].num[0]=cw[d].cnt[0]=0;
    int same=0,mid=(l+r)>>1;
    for(int i=mid;i>=l;--i){
        if(sor[mid]==sor[i])same++;
        else break;
    }
    int lpos=l,rpos=mid+1,cnt=0;
    for(int i=l;i<=r;++i){
        if(cw[d].num[i]<sor[mid]){
            cw[d+1].num[lpos++]=cw[d].num[i];
            cnt++;
        }else if(cw[d].num[i]==sor[mid]&&same){
            same--;cnt++;
            cw[d+1].num[lpos++]=cw[d].num[i];
        }else{
            cw[d+1].num[rpos++]=cw[d].num[i];
        }
        cw[d].cnt[i]=cnt;
    }
    build(l,mid,d+1);
    build(mid+1,r,d+1);
}
int query(int l,int r,int L,int R,int k,int d){
    if(l==r)return cw[d].num[l];
    int mid=(l+r)>>1,newl,newr,left=0,sum_in_left;
    if(l==L){
        sum_in_left=cw[d].cnt[R];
    }else{
        left=cw[d].cnt[L-1];
        sum_in_left=cw[d].cnt[R]-left;
    }
    if(k<=sum_in_left){
        newl=l+left;
        newr=newl+sum_in_left-1;
        return query(l,mid,newl,newr,k,d+1);
    }else{
        newl=mid+L-l+1-left;
        newr=newl+R-L+1-sum_in_left-1;
        return query(mid+1,r,newl,newr,k-sum_in_left,d+1);
    }
}
int main(){
    int tim;scanf("%d",&tim);
    int T=0;
    while(tim--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&sor[i]);
            cw[0].num[i]=sor[i];
        }
        sort(sor+1,sor+1+n);
        build(1,n,0);
        printf("Case %d:\n",++T );
        for(int i=0,u,v,w;i<m;++i){
            scanf("%d%d%d",&u,&v,&w);
            u++;v++;
            int l=1,r=v-u+1,mid,ans=0,tmp;
            while(l<=r){
                mid=(l+r)>>1;
                tmp=query(1,n,u,v,mid,0);
                if(tmp<=w){
                    l=mid+1;
                    ans=mid;
                }else{
                    r=mid-1;
                    ans=mid-1;
                }
            }
            printf("%d\n",ans );
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39599067/article/details/80586932