• Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)D(树状数组)


    //树状数组中数组的特性,有更巧妙的方法。
    //我们知道在树状数组中,对于数组tree[i],它所维护的区间为[i−lowbit(i)+1,i]
    //所以对于tree[2^i],它所维护的区间就为[1,2^i]。
    //所以就可以利用此特性加上树状数组的操作,维护一个类似倍增方法,并且支持在线修改操作。
    #define HAVE_STRUCT_TIMESPEC
    #include<bits/stdc++.h>
    using namespace std;
    long long a[200007],tree[200007],ans[200007];
    long long lowbit(long long x){//找到最低位的1
    return x&(-x);
    }
    void update(long long x,long long val){//更新前缀和
    for(long long i=x;i<=200007;i+=lowbit(i))
    tree[i]+=val;
    }
    /*
    long long query(int x){//树状数组求前缀和
    long long ans=0;
    for(long long i=x;i;i-=lowbit(x))
    ans+=tree[i];
    return ans;
    }
    */
    long long solve(long long k,long long n){//找到前缀和(sum1~x)为k的x
    long long num=0,sum=0;
    for(long long i=21;i>=0;--i){
    if(num+(1<<i)<=n&&sum+tree[num+(1<<i)]<=k){
    num+=1<<i;
    sum+=tree[num];
    }
    }
    return num+1;//返回x+1
    }
    int main(){
    long long n;
    cin>>n;
    for(long long i=1;i<=n;++i){
    update(i,i);//预处理前缀和
    cin>>a[i];
    }
    for(long long i=n;i;--i){//从后向前扫
    ans[i]=solve(a[i],n);//找到1+2+3+...+x==a[i],ans[i]=x+1
    update(ans[i],-ans[i]);//将比ans[i]大的数的前缀和中都减去ans[i],因为ans[i]这个数字已经在它们的后面了
    }
    for(long long i=1;i<=n;++i)
    cout<<ans[i]<<" ";
    return 0;
    }

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    spring----RESTful API
    spring----模块之间的通讯问题
    PHP错误与异常处理
    微信支付:curl出错,错误码:60
    jquery判断checkbox是否选中
    微信网页授权的问题
    TP5更新数据成功,但判断结果不符
    190719有个织梦专题标题长度限制问题
    判断手机浏览器还是微信浏览器(PHP)
    TP5关联模型出现疑问,待解决
  • 原文地址:https://www.cnblogs.com/ldudxy/p/11435406.html
Copyright © 2020-2023  润新知