フェンウィックツリー[] [] 2019hduマルチ学校は答えを探します

問題の意味:私は、我々は、入力シーケンスに応じて、小から大へ、離散すべて0に低減選択の最小数からI-1~1、及び1μm未満にプレフィックスを確保するためには、各ツリートラバーサルに挿入されています位置配列をソートした後、二つの配列の位置プレフィックスツリーとはミリアンペアに等しい/よりだけ少ない確保[I](iは現在必須)、大規模に小さいので、既存の小選挙限り、大きいことを保証するために削除されました。

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
using namespace std;
const int N = 200000 + 5;
int q,n;
ll m;
struct node
{
    int num;
    ll sum;
}c[200005];
struct nod
{
    int id;
    ll w;
}a[200005];
int mp[200005];
bool cmp(nod a,nod b)
{
    if(a.w==b.w)
        return a.id<b.id;
    return a.w<b.w;
}
void add(int x,ll y)
{
    for(;x<=n;x+=x&-x)
    {
        c[x].sum+=y;
        c[x].num++;
    }
}
ll ask_sum(int x)
{
    ll ret=0;
    for(;x;x-=x&-x)
    {
        ret+=c[x].sum;
        //cout<<x<<endl;
    }
    return ret;
}
ll ask_num(int x)
{
    ll ret=0;
    for(;x;x-=x&-x)
    {
        ret+=c[x].num;
    }
    return ret;
}
int half_find(ll x)
{
    int l=0,r=n;
    int mid=(l+r)>>1;
    while(l<=r)
    {
        //cout<<mid<<endl;
        mid=(l+r)>>1;
        if(ask_sum(mid)>x)
        {
            r=mid-1;
        }
        else
        {
            l=mid+1;
        }
        //cout<<l<<" "<<r<<" "<<mid<<endl;
    }
    //cout<<r<<endl;
    return ask_num(r);
}
int main()
{
    int x=3;
    //for(;x;x-=x&-x)
        //cout<<x<<endl;
    scanf("%d",&q);
    //cout<<ask_num(7)<<endl;
    while(q--)
    {
        scanf("%d %lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i].w);
            a[i].id=i;
            c[i].num=c[i].sum=0;
        }
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            //cout<<a[i].id<<endl;
            mp[a[i].id]=i;
        }
        printf("0");
        add(mp[1],a[mp[1]].w);
        for(int i=2;i<=n;i++)
        {
            printf(" %lld",i-1-half_find(m-a[mp[i]].w));
            add(mp[i],a[mp[i]].w);
        }
        printf("\n");
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/Diliiiii/p/11266167.html