zoukankan      html  css  js  c++  java
  • Codeforces 1208D Restore Permutation

    题目链接:https://www.luogu.org/problem/CF1208D

    题意:现在有一个从1n的一个全排列,但是你不知道这个排列到底是什么,但是你有一个sum[i],sum[i]的值是所有满足j<i并且a[j]<a[i]的值之和,给出每个点的sum[i],求出原本的全排列

    分析:我们从最后一个点n开始看,sum[n]肯定表示的是一段连续的都比a[n]小的的从1到j的数的和,根据这个和我们可以找出a[n]

    而sum[n-1]表示的是一段连续的都比a[n-1]小的的从1到k的数的和(这里注意,如果本身a[n]也比a[n-1]小的话,这个和里是不包含a[n]的,也就是说事实上此时的sum[n-1]表示的是[1,a[n]),(a[n],k)的和

    那么思路就出来了,我们可以从后往前一个个确定,确定了一个数之后就把那个数赋为0 ,之后找和的时候就不会遇到那个数了

    也就是说会用单单点修改,和查询时哪个区间的和 线段树即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=1e18;
    const int maxn=2e5+7; 
    const int mod=1e9+7;
    #define mem0(a) memset(a,0,sizeof(a))
    #define meminf(a) memset(a,0x3f,sizeof(a))
    #define ls rt<<1
    #define rs rt<<1|1
    ll a[maxn],ans[maxn];
    ll dat[maxn<<2];
    void add(int rt,int l,int r,int x,int y){
        if(l==r){
            dat[rt]+=y;
            return ;
        }
        ll mid=(l+r)>>1;
        if(x<=mid)add(ls,l,mid,x,y);
        else add(rs,mid+1,r,x,y);
        dat[rt]=dat[ls]+dat[rs];
    }
    ll query(int rt,int l,int r,ll v){
        if(l==r){
            return l;
        }
        ll mid=(l+r)>>1;
        if(dat[ls]>v)return query(ls,l,mid,v);
        else return query(rs,mid+1,r,v-dat[ls]);
    }
    int main(){
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%I64d",&a[i]);
            add(1,1,n,i,i);
        }
        for(int i=n;i>0;i--){
            ans[i]=query(1,1,n,a[i]);
            add(1,1,n,ans[i],-ans[i]);
            //将第i个数赋为0,之后就不会加了 
        }
        for(int i=1;i<n;i++)printf("%I64d ",ans[i]);
        printf("%I64d
    ",ans[n]); 
        return 0;
    }
  • 相关阅读:
    鼠标移动,背景变色
    datatable 删除行
    GridView新增一行,更新所有行實現
    让层垂直居中于浏览器窗口
    extjs学习笔记(转)
    Extjs中的panel
    JDK和JRE的区别(转)
    EXTJS中form添加按钮触发事件
    web.xml详解
    Oracle数据库中的诊断文件(转)
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11624286.html
Copyright © 2011-2022 走看看