zoukankan      html  css  js  c++  java
  • 区间第k大问题 权值线段树 hdu 5249

    先说下权值线段树的概念吧  

    权值平均树 就是指区间维护值为这个区间内点出现次数和的线段树

    用这个加权线段树 解决第k大问题就很方便了 

    int query(int l,int r,int rt,int k)//找第k大的数
    {
        if(l==r) return l;
        int m=(l+r)/2;
        if(k<=sum[rt<<1]) return query(lson,k);//看左儿子的sum是否大于k大于的话 说明第k大的树在左儿子(利用出现的次数进行比对---建树的时候 边界是递增的)
        else return query(rson,k-sum[rt<<1]);
    }
    最后说一下使用权值线段树容易出现的问题 在建树的过程中 树的最大边界得包括我们需要的数据 那么问题来了 当数据很大的时候 不久爆内存了
    这里得将数据离散化一下
    什么是离散化呢 就是将数据映射成紧凑的数据 三个步骤
    1.排序 2.去重 unqinue()函数。。 3.二分定位 用位置映射数据(lower_bound函数。。)

    附上吴迎学长离散化的标准代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int a[100],b[100],c[100],n;
    int solve()//离散化
    {
        for(int i=0;i<n;i++) b[i]=a[i];
        sort(b,b+n);
        int m=unique(b,b+n)-b;//去重
        for(int i=0;i<n;i++) c[i]=lower_bound(b,b+m,a[i])-b;//二分找对应位置
        for(int i=0;i<n;i++) printf("%d ",c[i]);
    }
    int main()
    {
    
        freopen("in.txt","r",stdin);
        cin>>n;
        for(int i=0;i<n;i++) cin>>a[i];
        solve();
        return 0;
    }

    再说说5249吧。,。 看了下吴迎学长的代码。。 感触挺深。 自己按照思路码了一遍 库函数好用

    #include<cstdio>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define lson l,m,rt<<1 //显得代码比较精简
    #define rson m+1,r,rt<<1|1
    #define maxn 10005
    using namespace std;
    int sum[maxn<<2];
    int n,a[maxn],b[maxn],c[maxn];
    void Pushup(int rt)
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            sum[rt]=0;
            return ;
        }
        int m=(l+r)/2;
        build(lson);
        build(rson);
        Pushup(rt);
    }
    void updata(int l,int r,int rt,int temp,int flag)
    {
        if(l==r)
        {
            sum[rt]+=flag;
            return;
        }
        int m=(l+r)/2;
        if(temp<=m) updata(lson,temp,flag);//
        else updata(rson,temp,flag);
        Pushup(rt);
    }
    int query(int l,int r,int rt,int k)//找第k大的数
    {
        if(l==r) return l;
        int m=(l+r)/2;
        if(k<=sum[rt<<1]) return query(lson,k);
        else return query(rson,k-sum[rt<<1]);
    }
    int main()
    {
        int t=0;
        while(~scanf("%d",&n))//由于需要离散化的过程 我们需要离线写
        {
            char op[10];
            queue<int> que;
        //    freopen("in.txt","r",stdin);
            for(int i=1;i<=n;i++)
            {
                scanf("%s",op);
                if(op[0]=='i') scanf("%d",&a[i]);
                else if(op[0]=='o') a[i]=-1;
                else a[i]=-2;
            }
            int m=1;
            for(int i=1;i<=n;i++)
            {
                if(a[i]>=0) b[m]=a[i],c[m++]=a[i];
            }
            sort(c+1,c+m);
            int mm=unique(c+1,c+m)-(c+1);//离散的排序 去重 unique函数的参数为需要去重的范围 返回值为最后一个去重过程的函数 还有就是这个函数只对相邻的数去重
            build(1,mm,1);
            printf("Case #%d:
    ",++t);
        //    cout<<mm<<endl;
        //    for(int i=1;i<=mm;i++) cout<<c[i]<<endl;
            for(int i=1;i<=n;i++)
            {
                if(a[i]>=0)
                {
                   int temp=lower_bound(c+1,c+mm+1,a[i])-c;//离散坐标对应
                   updata(1,mm,1,temp,1);
                //   cout<<temp<<endl;
                 //  for(int i=1;i<=7;i++) cout<<"in"<<sum[i]<<endl;
                   que.push(a[i]);
                }
                else if(a[i]==-1)
                {
                   int ret=que.front();
                   int temp=lower_bound(c+1,c+mm+1,ret)-c;// 在c数组中找到第一个不小于ret的数
                   updata(1,mm,1,temp,-1);
                //for(int i=1;i<=7;i++) cout<<' '<<"out"<<sum[i]<<endl;
                   que.pop();
                }
                else
                {
                  // cout<<que.size()/2+1<<endl;
                   printf("%d
    ",c[query(1,mm,1,(que.size()/2+1))]);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    MySQL Community Server 8.0.16
    Python的编码规范
    Python 的语言特性
    spark笔记 环境配置
    C#委托实现工厂规则注入
    特性与元数据
    可输入的模糊搜索ComBox控件
    ASPX页面输出datatable的一种方法
    QRcode生成二维码,保存二维码图片到服务器
    SQL语句的随机值与行号,字符串拼接
  • 原文地址:https://www.cnblogs.com/z1141000271/p/5764845.html
Copyright © 2011-2022 走看看