Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-D. Restore Permutation-构造+树状数组


【Problem Description】

​ 给你一个长度为\(n\)的数组,第\(i\)个元素\(s_i\)表示一个排列中第\(i\)个元素之前,并且小于\(p_i\)的元素的和。求出满足此条件的排列。

【Solution】

​ 假设\(n=5\),\(s[]=\{0,0,3,7,3\}\)。从后往前看,最后一个值为\(3\),表示存在一个数\(x\),使得\(1+2+\dots+x=3\)。易知\(x=2\),所以\(p_5=x+1=3\)。然后第二个值为\(7\),表示存在一个数\(x\),使得\(1+2+\dots +x-3=7\)。减\(3\)是因为\(p_5=3\),不可能出现在\(p_4\)之前。所以可知\(x=4\),所以\(p_4=x+1=5\)。同理利用此方法可以求出此排列。

​ 上述方法其实就是在找一个最大的\(x\),使得将所有满足\(1\le y\le x\),并且未出现过的\(y\)值相加使其等于\(s_i\),则\(p_i=x+1\)。可以想到用树状数组维护前缀和,用二分查找最大的满足条件的\(x\)。每求得一个数,就将此数清零即可。

​ 但其实用树状数组中数组的特性,有更巧妙的方法。我们知道在树状数组中,对于数组\(tree[i]\),它所维护的区间为\([i-lowbit(i)+1,i]\),所以对于\(tree[2^i]\),它所维护的区间就为\([1,2^i]\)。所以就可以利用此特性加上树状数组的操作,维护一个类似倍增方法,并且支持在线修改操作。

​ 例如求\(sum[1+2+\dots10]=tree[2^3]+tree[2^3+2^1]\)


【Code】

/*
* @Author: Simon
* @Date: 2019-08-26 18:14:20
* @Last Modified by: Simon
* @Last Modified time: 2019-08-26 20:12:53
*/
#include<bits/stdc++.h>
using namespace std;
typedef int Int;
#define int long long
#define INF 0x3f3f3f3f
#define maxn 200005
int a[maxn],tree[maxn],ans[maxn];
inline int lowbit(int x){
return x&(-x);
}
inline void update(int x,int val){
for(int i=x;i<maxn;i+=lowbit(i)){
tree[i]+=val;
}
}
inline int query(int x){
int ans=0;
for(int i=x;i>0;i-=lowbit(i)){
ans+=tree[i];
}
return ans;
}
int solve(int k,int n){
int num=0,sum=0;
for(int i=21;i>=0;i--){
if(num+(1<<i)<=n&&sum+tree[num+(1<<i)]<=k){//求一个最大num,使得sum[1+2+...+num]=k
num+=1<<i;
sum+=tree[num];
}
}
return num+1;
}
Int main(){
#ifndef ONLINE_JUDGE
//freopen("input.in","r",stdin);
//freopen("output.out","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++){
update(i,i)/*初始所有值都存在*/;cin>>a[i];
}
for(int i=n;i>=1;i--){
ans[i]=solve(a[i],n);
update(ans[i],-ans[i]);//将ans[i]清零。
}
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<endl;
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}

Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-D. Restore Permutation-构造+树状数组的更多相关文章

  1. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造

    Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造 [Problem Descripti ...

  2. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构

    Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构 [Problem ...

  3. CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组

    题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有 ...

  4. CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)

    转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interestin ...

  5. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) F. Bits And Pieces sosdp

    F. Bits And Pieces 题面 You are given an array

  6. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) G. Polygons 数论

    G. Polygons Description You are given two integers

  7. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) (1208F,1208G,1208H)

    1208 F 大意:  给定序列$a$, 求$\text{$a_i$|$a_j$&$a_k$}(i<j<k)$的最大值 枚举$i$, 从高位到低位贪心, 那么问题就转化为给定$x$ ...

  8. RMQ+差分处理(Let Them Slide)Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)

    题意:https://codeforc.es/contest/1208/problem/E 现有n行w列的墙,每行有一排连续方块,一排方块可以左右连续滑动,且每个方块都有一个价值,第i 列的价值定义为 ...

  9. 线段树维护最后一个0的位置(Restore Permutation)Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)

    题意:https://codeforc.es/contest/1208/problem/D 给你长度为n的序列,s[i]的值为p[1]到p[i-1]中比p[i]小的数的和,让你求出p序列. 思路: 首 ...

随机推荐

  1. Linux下tar的安装方式

    tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...

  2. (语法基础)浅谈面向切面编程(AOP)

    一:前言 面向切面编程是一个很重要的编程思想,想要写出一个便于维护的程序,理解AOP并且能熟练的在实际编程中合理的运用AOP思想是很有必要的 二:AOP的基本概念 基础概念:AOP中文翻译面向切面编程 ...

  3. 深层目录文件复制,C# 递归,录音录像图片文件过多,用于测试程序

    /// <summary> /// 录音录像图片文件过多只复制目录的前几个文件,用于测试程序 /// d:\file/images/2019-10/01/01/xxxxx.jpg(前几个文 ...

  4. DRF框架(四)——单整体改(put)、单局部改(patch)、群局部改(patch)

    单整体改   单指的是单独一条数据,整体指这条数据的所有字段都必须传值修改 基于上篇文章的代码修改,序列化层不用变,只修改views.py 1) 单整体改,说明前台要提供修改的数据,那么数据就需要校验 ...

  5. jdbc 简单示例和优缺点

    一个使用JDBC的例子: Class.forName("com.mysql.cj.jdbc.Driver"); //加载驱动 Connection connection = Dri ...

  6. N皇后问题的python实现

    数据结构中常见的问题,最近复习到了,用python做一遍. # 检测(x,y)这个位置是否合法(不会被其他皇后攻击到) def is_attack(queue, x, y): for i in ran ...

  7. 关于使用KubeSphere中的docker配置Harbor仓库http访问docker login登陆报错的解决办法

    # 先进入harbor目录中,停止harbor docker-compose stop # 然后修改docker相关文件 # 第一种方式:修改/etc/docker/daemon.json { &qu ...

  8. Ubuntu中安装(升级)GraphicsMagick

    1 前言 采用官方下载安装包然后强制安装升级Ubuntu中有的老版本gmagick-1.3.28,升级到gmagick-1.3.31 仅用来记录使用. 2.准备工作 1.下载安装包 https://s ...

  9. python 1.使用djano前的提前准备:虚拟环境 virtualenv

    首先想要学习django我们就得了解一下虚拟环境,什么是虚拟环境?他有什么用? 1.首先虚拟环境就相当于一个一个的盒子,这个盒子里面安装的软件不会对其他的盒子造成任何影响. 2.如果你现在用Djang ...

  10. 2017-07-25 PDO预处理以及防止sql注入

    首先来看下不做任何处理的php登录,首先是HTML页面代码 <html> <head><title>用户登录</title></head> ...