• 19市赛 树状数组 第k个小的糖果


     1 int find_kth(int k)
     2 {
     3     int ans = 0, cnt = 0, i;
     4     for (i = 20; i >= 0; i--)/
     5     {
     6         ans += (1 << i);
     7         if (ans >= maxn|| cnt + c[ans] >= k)
     8             ans -= (1 << i);
     9         else
    10             cnt += c[ans];
    11     }
    12     return ans + 1;
    13 }

    题意:

    口袋里可以放进不同大小的糖果,也可以拿出不同大小的糖果。查询过程中第k小的糖果体积是多少

    输入T,有T组,接下来是输入m次操作

    m行输入op和x

    当op等于1的时候,放进x大小的糖果

    当op等于2的时候,拿进x大小的糖果

    当op等于3的时候,查询第x小的糖果,并输出答案

    思路:二分+树状数组(比赛时限)

    这里写一个优化的树状数组的写法

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define inf 0x3f3f3f3f
    #define ll long long
    #define lowbit(b) b&(-b)
    using namespace std;
    const int maxn=1e5+10;
    int c[maxn],f[20];
    inline int read() {
        char ch = getchar(); int x = 0, f = 1;
        while(ch < '0' || ch > '9') {
            if(ch == '-') f = -1;
            ch = getchar();
        } while('0' <= ch && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        } return x * f;
    }
    inline void updata(int x, int y){
        for (int i = x; i <= maxn; i += lowbit(i)){
            c[i] += y;
        }
    }
    int main()
    {
    int t,i;f[0]=1;
    for(i=1;i<=17;i++){
        f[i]=f[i-1]*2;
    }
        t=read();
        while(t--){
            for(i=0;i<maxn;i++){c[i]=0;}
            int m;
           m=read();
            for(i=0;i<m;i++){
                int op,x;
                op=read();x=read();
                if(op==1){
                    updata(x,1);
                }
                else if(op==2){
                    updata(x,-1);
                }
                else{
                    int ans=0,sum=0,j;
                    for(j=17;j>=0;j--){
                        ans+=f[j];
                        if(ans>=maxn || sum+c[ans]>=x){
                            ans-=f[j];
                        }
                        else{
                            sum+=c[ans];
                        }
                    }
                    printf("%d
    ",ans+1);
                }
            }
        }
        return 0;
    }
    /*
    2
    3
    1 2
    1 2
    3 1
    4
    1 2
    1 3
    2 2
    3 1
    */

    顺便放一下逆序数的板子

    #define N 1010
    int c[N]; 
    int n;
    int lowbit(int i)
    {
        return i&(-i);
    }
    void insert(int i,int x)
    {
        while(i<=n){
            c[i]+=x;
            i+=lowbit(i);
        }
    }
    
    int getsum(int i)
    {
        int sum=0;
        while(i>0){
            sum+=c[i];
            i-=lowbit(i);
        } 
        return sum;
    }
    void output()
    {
        for(int i=1;i<=n;i++) cout<<c[i]<<" ";
        cout<<endl;
    }
    int main()
    {
        while(cin>>n){
            int ans=0;
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++){
                int a;
                cin>>a;
                insert(a,1);
                ans+=i-getsum(a);//统计当前序列中大于a的元素的个数
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    cocos2d-3.0 Helloworld::onTouchMoved的处理机制的推測
    一个Nodejs的简单计算測试程序
    js正則表達式语法
    奇妙的go语言(网页下载)
    java环境变量配置
    【数据结构与算法】二叉树深度遍历(非递归)
    $.each 和$(selector).each()的差别
    HDU-2844-Coins(多重背包)
    curl命令具体解释
    Arduino 数码管LED屏驱动
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/12189985.html
Copyright © 2020-2023  润新知