2019 Multi-University Training Contest 3 Find the answer (+ discrete binary tree arrays +)

Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=6609

Title effect: Given a sequence containing a number n, and a m, for each i (1 <= i <= n) is determined by how many number of i-1 before the change will need at least 0 before, in order to make the number i is smaller than m and

Problem-solving ideas: it is easy to think that we should be a relatively large number of changes to 0, the answer is the best. So we discharge them directly to a sequence of discrete look, they correspond to numbers in the tree, the tree nodes keep two things, one is the right node of the sum, and one that contains the number of numbers, each query , the first i-1 before the number of updates to the tree, can ensure that the number of the latter does not affect the answers, and the number i is assumed that before the sum-m = x, then we find a one-half as long as the largest L, so that the interval [l, n] x greater than or equal to it, so the answer is the interval [l, n] is the number of number.

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n,m,ans[maxn];
struct node{
    int val,id,rk;
}a[maxn];
bool cmp1(node x,node y){
    return x.val<y.val;
}
bool cmp2(node x,node y){
    return x.id<y.id;
}
ll sum[maxn],num[maxn];
int Ans;
int lowbit(int x){
    return x&(-x);
}
void add(int x,ll val){
    while(x<=n){
        num[x]++;
        sum[x]+=val;
        x+=lowbit(x);
    }
}
ll ask(int x){
    ll res=0;
    while(x){
        Ans+=num[x];
        res+=sum[x];
        x-=lowbit(x); 
    }
    return res;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        memset(num,0,sizeof(num));
        memset(sum,0,sizeof(sum));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i].val);
            a[i].id=i;
        }
        sort(a+1,a+1+n,cmp1);
        for(int i=1;i<=n;i++)
            a[i].rk=i;
        sort(a+1,a+1+n,cmp2);
        ll tmp=0;
        for(int i=1;i<=n;i++){
            tmp+=a[i].val;
            if(tmp<=m)ans[i]=0;
            else{
                ll x=tmp-m;
                int l=0,r=n;
                Ans=0;
                ll s1=ask(n); ll Ans1=Ans;
                while(l<=r){
                    int mid=l+r>>1;
                    Ans=0;
                    ll s2=ask(mid); ll Ans2=Ans;
                    if(s1-s2>=x){
                        ans[i]=Ans1-Ans2;
                        l=mid+1; 
                    }else r=mid-1;
                }
            }
        //    cout<<a[i].rk<<" "<<a[i].val<<endl;
            add(a[i].rk,a[i].val);
        }
        for(int i=1;i<=n;i++)
            printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/zjl192628928/p/11270094.html