• [Codeforces 1208D]Restore Permutation (树状数组)


    [Codeforces 1208D]Restore Permutation (树状数组)

    题面

    有一个长度为n的排列a。对于每个元素i,(s_i)表示(sum_{j=1,a_j<a_i}^i a_j).即前面比它小的元素的值之和。
    给出(s_1,s_2 dots s_n),求a

    分析

    考虑如何求(a_n),(s_n)实际上表示的是1~n中比(a_n)小的所有数的和,可以直接求出(a_n)

    然后我们可以倒序求(a_i),求到(a_i)的时候,我们已经知道(a_i)前面有哪些数,只是不知道顺序。维护一个数据结构存储这些数的集合,并存储从小到大排列后的前缀和,然后二分出最后一个前缀和(leq s_i)的位置。
    比如最后一个样例:

    input:
    5
    0 1 1 1 10
    
    output:
    1 4 3 2 5
    

    我们求到第4个数的时候,由于第5个数已经求出来是5,那前面的数就是{1,2,3,4},2之前的前缀和是1,1之前的前缀和是0,那么二分出的点就是2.

    具体实现可以用树状数组,初始时候给第i个位置加i,求出某个数的值为x之后把第x个位置-x,相当于把x移出集合

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #define maxn 200000
    using namespace std;
    typedef long long ll;
    int n;
    struct fenwick_tree{
    	ll c[maxn+5];
    	inline int lowbit(int x){
    		return x&(-x);
    	}
    	inline void update(int x,int v){
    		for(int i=x;i<=n;i+=lowbit(i)){
    			c[i]+=v;
    		}
    	}
    	inline ll query(int x){
    		ll ans=0;
    		for(int i=x;i>0;i-=lowbit(i)) ans+=c[i];
    		return ans;
    	}
    }T;
    ll a[maxn+5];
    int ans[maxn+5]; 
    int bin_search(int l,int r,ll sum){
    	int ans=n;
    	int mid;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(T.query(mid-1)<=sum){
    			ans=mid;
    			l=mid+1;
    		}else r=mid-1;
    	}
    	return ans;
    }
     
     
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%I64d",&a[i]);
    	}	
    	for(int i=1;i<=n;i++) T.update(i,i);
    	for(int i=n;i>=1;i--){
    		int k=bin_search(1,n,a[i]);
    		ans[i]=k;
    		T.update(k,-k);
    	}
    	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    }
    
  • 相关阅读:
    mybatis(1.2)
    Could not find resource mybatis.xml 找不到mybatis主配置文件的三种解决方式
    mybatis(1)
    linux笔记(一)
    javaScript(笔记1)
    过滤器 防止用户恶意登陆
    用户注册调优 及Connection对象
    请求转发的实现及其优缺点
    重定向的实现及其优缺点
    http状态码
  • 原文地址:https://www.cnblogs.com/birchtree/p/11418886.html
Copyright © 2020-2023  润新知