2018江苏省省赛c题 (hdu6278)

题意:找到序列中大于某个数ans的总个数sum,并且sum>=ans的最大的ans。
题解:简单修改主席树,然后秒过。

#include<bits/stdc++.h>
#define lson l,m
#define rson m+1,r
using namespace std;

const int maxn=100005;

struct Node {
    int l,r,sum;
} p[3000010]; //毕竟有100000颗线段树。

int T[maxn],a[maxn],Hash[maxn],cnt=0;

int build(int l,int r) {
    int rt=(++cnt);
    if(l==r) {
        return p[rt].sum=0;
    }
    int m=(l+r)>>1;
    p[rt].l=build(lson);//注意这里的左右子树不在通过计算得到
    p[rt].r=build(rson);//因为多棵线段树的左右节点掺杂,不存在原来线段树的计算规律。
    return rt;
}
int update(int pre,int l,int r,int x) {
    int rt=(++cnt);//rt为新加的一条树链的节点
    p[rt].sum=p[pre].sum+1;
    p[rt].l=p[pre].l;
    p[rt].r=p[pre].r;
    if(l==r)return rt;
    int m=(l+r)>>1;
    if(x<=m)p[rt].l=update(p[pre].l,lson,x);
    else p[rt].r=update(p[pre].r,rson,x);
    return rt;
}
int query(int u,int v,int l,int r,int k) {//注意这里的k不是第k大,而是右子树的数字总和。
    if(l==r) {
        return l;
    }
    int m=(l+r)>>1;
    int num=p[p[v].r].sum-p[p[u].r].sum+k;
    if(num<=m)return query(p[u].l,p[v].l,lson,num);//右边的数一定大于左边
    else return query(p[u].r,p[v].r,rson,k);//父亲的右儿子一定比自己大
}
int main() {
    int t;
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF) {
        cnt=0;

        for(int i=1; i<=n; i++) {
            scanf("%d",&a[i]);
            Hash[i]=a[i];
        }
        T[0]=build(1,n);
        for(int i=1; i<=n; i++) {
            T[i]=update(T[i-1],1,n,a[i]);
        }
        while(m--) {
            int l,r,k;
            scanf("%d%d",&l,&r);
            int x=query(T[l-1],T[r],1,n,0);
            printf("%d\n",x);
        }
    }
    return 0;
}
//不用结构体的模板
#include<bits/stdc++.h>
#define lson l, m
#define rson m+1, r
using namespace std;
const int N=1e5+5;
int L[N<<5], R[N<<5], sum[N<<5];
int tot;
int a[N], T[N], Hash[N];
int build(int l, int r)
{
    int rt=(++tot);
    sum[rt]=0;
    if(l<r)
    {
        int m=(l+r)>>1;
        L[rt]=build(lson);
        R[rt]=build(rson);
    }
    return rt;
}

int update(int pre, int l, int r, int x)
{
    int rt=(++tot);
    L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+1;
    if(l<r)
    {
        int m=(l+r)>>1;
        if(x<=m)
            L[rt]=update(L[pre], lson, x);
        else
            R[rt]=update(R[pre], rson, x);
    }
    return rt;
}

int query(int u, int v, int l, int r, int k)
{
    if(l>=r)
        return l;
    int m=(l+r)>>1;
    int num=sum[R[v]]-sum[R[u]]+k;
    if(num<=m)
        return query(L[u], L[v], lson, num);
    else
        return query(R[u], R[v], rson, k);
}

int main()
{
    int t;
    int n, m;
     while(scanf("%d%d", &n, &m)!=EOF)   
    {
        tot=0;

        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
            Hash[i]=a[i];
        }
        //sort(Hash+1, Hash+n+1);
        //int d=unique(Hash+1, Hash+n+1)-Hash-1;
        T[0]=build(1, n);
        for(int i=1; i<=n; i++)
        {
        //    int x=lower_bound(Hash+1, Hash+d+1, a[i])-Hash;
            T[i]=update(T[i-1], 1, n, a[i]);
        }
        while(m--)
        {
            int l, r, k;
            scanf("%d%d", &l, &r);
            int x=query(T[l-1], T[r], 1, n, 0);
            printf("%d\n", x);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35160381/article/details/80458649
今日推荐