zoukankan      html  css  js  c++  java
  • 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;
    }

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    js的基本数据类型有哪些?
    UML 类图
    三种代理模式
    jsp 知识点
    httpServlet
    Qt时间&日期
    Microsoft visual studio C 运行时库 在 xx.exe中检测到一个错误
    C++调用COM之错
    PCL中的bug修改
    Qt使用SQLite
  • 原文地址:https://www.cnblogs.com/ldudxy/p/11435406.html
Copyright © 2011-2022 走看看