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;
}
原文地址:https://www.cnblogs.com/luoyugongxi/p/12189985.html