题目:

  Nk 最近喜欢上了研究逆序数,给出一个由 1…n 组成的数列 a1,a2,a3…an,

  a1的逆序数就是在 a2…an 中,比 a1 小的数的数量,而 a2 的逆序数就是 a3….an 中比 a2 小的数的数量,以此类推。

  例如,数列 5,3,4,2,1 的逆序数序列就是 4,2,2,1,0.

  那么,如果给出一个数列的逆序数序列,你能不能还原得到他的原数列?

  ★数据输入

  每个测试数据是一个正整数 n。代表数列长度(1<=n<=500),并且原数列中的值的范围是[1,n]。

  然后输入 n 个正整数 ai(0<=ai<n)

  ★数据输出

  输出原始数列,两个数字间中间用空格隔开。

输入示例 输出示例
5
4 2 2 1 0
5 3 4 2 1

  分析下问题,不难发现,第一个数字填入时,除了自己以外的所有数字都在它的后面,因此第一个数字为4。我们可以将1-n所有数字作为一个集合,当第i个数后有ai个比他小的数时,集合中第ai+1大的数就是第i个数字,随后将这个数字从集合中删除。由于n数值过小(虽然线段树不交但是也不至于小到只有500),可以使用链表来完成,也可以使用set进行维护,复杂度均为$O(n^{2})$,当然,set维护写起来比较方便,建议用set维护。这里分享$O(nlogn)$做法,使用权值线段树。

先贴上set代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int,int> pii;
#define rep(i,x,y) for(int i=x;i<y;i++)
#define rept(i,x,y) for(int i=x;i<=y;i++)
#define per(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define fi first
#define se second
#define mes(a,b) memset(a,b,sizeof a)
const int inf=0x3f3f3f3f; set<int> s;
set<int> ::iterator pos;
int main()
{
ios::sync_with_stdio(false);
cin.tie();
int n;
cin>>n;
rept(i,,n)
s.insert(i);
rept(i,,n)
{
if(i-) cout<<" ";
int x;
cin>>x;
pos=s.begin();
for(int i=;i<x;i++,pos++);
cout<<*pos;
s.erase(pos);
}
cout<<"\n";
return ;
}

  对于1-n所有数,建成线段树,每个点标记第i个数为数组中第几大,对于线段树维护区间最大值,每输入一个ai,对于线段数找出大于ai的第一个点,即左区间有大于ai的找左区间,左区间没有则查询右区间。假设数组中第i个数为bi,将线段树中bi的值赋值为0,然后将$[bi+1,n]$区间的每个元素减1即可。

贴上线段树AC代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int,int> pii;
#define rep(i,x,y) for(int i=x;i<y;i++)
#define rept(i,x,y) for(int i=x;i<=y;i++)
#define pb push_back
#define fi first
#define se second
#define mes(a,b) memset(a,b,sizeof a) const int maxn=;
ll arrcy[];
class Tree//线段树
{
public:
int l,r;
ll plus,val;
Tree()
{
l=r=val=plus=;
}
}tree[maxn<<]; void build(int id,int l,int r);
void add(int id,int l,int r,ll num);
void push_down(int id);
int find(int id,int num);
int main()
{
int n,x,ans;
cin>>n;
build(,,n);
rep(i,,n)
{
cin>>x;
ans=find(,x);
add(,ans+,n,-);
add(,ans,ans,-n);
cout<<ans<<" ";
}
return ;
} void build(int id,int l,int r)
{
tree[id].l=l;
tree[id].r=r;
if(l==r)
{
tree[id].val=l;
return ;
}
int mid=(l+r)/;
build(id*,l,mid);
build(id*+,mid+,r);
tree[id].val=max(tree[id*].val,tree[id*+].val);
}
void add(int id,int l,int r,ll num)
{
if(tree[id].l>=l&&tree[id].r<=r)
{
tree[id].plus+=num;
tree[id].val+=num;
return ;
}
if(tree[id].l>r||tree[id].r<l) return ;
push_down(id);
if(tree[id*].r>=l) add(id*,l,r,num);
if(tree[id*+].l<=r) add(id*+,l,r,num);
tree[id].val=max(tree[id*].val,tree[id*+].val);
}
void push_down(int id)
{
rept(j,id*,id*+)
{
tree[j].val+=tree[id].plus;
tree[j].plus+=tree[id].plus;
}
tree[id].plus=;
}
int find(int id,int num)
{
if(tree[id].l==tree[id].r) return tree[id].l;
push_down(id);
if(tree[id*].val>num) return find(id*,num);
else return find(id*+,num);
}

FZU2018级算法第二次作业 2.10 逆序数(权值线段树)的更多相关文章

  1. [NOIP2015模拟10.27] [JZOJ4270] 魔道研究 解题报告(动态开点+权值线段树上二分)

    Description “我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力.”——<The Grimoire of Marisa>雾雨魔理 ...

  2. FZU2018级算法第五次作业 m_sort(归并排序或线段树求逆序对)

    首先对某人在未经冰少允许情况下登录冰少账号原模原样复制其代码并且直接提交的赤裸裸剽窃行为,并且最终被评为优秀作业提出抗议! 题目大意: 给一个数组含n个数(1<=n<=5e5),求使用冒泡 ...

  3. 315. Count of Smaller Numbers After Self(二分或者算法导论中的归并求逆序数对)

    You are given an integer array nums and you have to return a new counts array. The counts array has ...

  4. FZU2018级算法第一次作业 1.1fibonacci (矩阵快速幂)

    题目 Winder最近在学习fibonacci 数列的相关知识.我们都知道fibonacci数列的递推公式是F(n)=F(n-1)+F(n-2)(n>=2 且n 为整数). Winder想知道的 ...

  5. FZU2018级算法第五次作业 missile(排序+枚举)

    在解题报告之前,首先对同一次作业中另外一题(求逆序对)某人在未经冰少允许情况下,擅自登录冰少账号,原模原样剽窃冰少代码,并且最终还被评为优秀作业的行为表示严正抗议! 题目大意: 二维平面上给出 n 个 ...

  6. FZU2018级算法第三次作业 3.16 station

    题目大意: 给出1-n共n个数的入栈顺序,可以随时出栈,求出栈的最大字典序. 输入示例 输出示例 51 2 3 4 5 5 4 3 2 1 54 2 5 3 1 5 3 2 4 1 题目分析: 假设目 ...

  7. js第二次作业——2019.10.16

    第一题:完成省城市的三级联动(包括湖南省),附代码和效果图. 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 </head> ...

  8. 2016级算法第二次上机-G.ModricWang's Real QuickSort

    873 思路 这是一道非常基础的题,目的是帮助大家回顾快排相关的知识.大家完成此题之后应该就对快排有比较深刻的印象了. 对于整个快排的流程,题目描述中已经给了清晰完整的伪代码.需要自己加工的部分就是, ...

  9. 2016级算法第二次上机-F.ModricWang's Number Theory II

    891 ModricWang's Number Theory II 思路 使得序列的最大公约数不为1,就是大于等于2,就是找到一个大于等于2的数,它能够整除序列中的所有数. 考虑使得一个数d整除数组中 ...

随机推荐

  1. 配置Notepad++

    Notepad++配置 1.自动换行 视图 - 自动换行 2.隐藏工具栏 设置 - 首选项... > 常用 > 工具栏 - 隐藏 3.隐藏菜单栏 设置 - 首选项... > 常用 & ...

  2. 微信小程序测试检查点

    1.权限测试 需要检查以下几种情况下微信用户访问的权限1)未授权微信登录小程序未授权时,一般使用一些业务功能的时候,都会弹出提醒:先授权再操作对应功能.或在提交数据到后台的时候,会提示补充相关身份信息 ...

  3. Web安全测试检查点

    Web安全测试检查点 上传功能 1.绕过文件上传检查功能 2.上传文件大小和次数限制 注册功能 1.注册请求是否安全传输 2.注册时密码复杂度是否后台检验 3.激活链接测试 4.重复注册 5.批量注册 ...

  4. web前端之es6对象的扩展

    1.属性的简洁表示法 2.属性名表达式 表达式作为对象的属性名 3.方法的 name 属性 例如:函数的name 属性,返回函数名. 4.Object.is() ES 比较两个值是否相等,只有两个运算 ...

  5. 23Flutter FloatingActionButton实现类似闲鱼App底部导航凸起按钮:

    /* 一.Flutter FloatingActionButton介绍 FloatingActionButton简称FAB,可以实现浮动按钮,也可以实现类型闲鱼app的底部凸起导航. child:子视 ...

  6. Qt编写自定义控件56-波浪曲线

    一.前言 波浪曲线控件,其实是之前一个水波进度条控件的一个核心,其实就是利用正弦曲线来生成对应的坐标进行绘制,把这个功能单独提取出来,是为了更详细的研究各种正弦余弦等拓展效果,当时写这个效果的时候,参 ...

  7. springboot集成调用Azkaban

    springboot集成调用Azkaban 一. 说明 1.Azkaban是由Linkedin公司推出的一个批量工作流任务调度器,主要用于在一个工作流内以一个特定的顺序运行一组工作和流程,它的配置是通 ...

  8. 123456---com.twoapp.xiaoxiaofeixingyuan---小小飞行员

    com.twoapp.xiaoxiaofeixingyuan---小小飞行员

  9. PAT 甲级 1061 Dating (20 分)(位置也要相同,题目看不懂)

    1061 Dating (20 分)   Sherlock Holmes received a note with some strange strings: Let's date! 3485djDk ...

  10. (三)java虚拟机内存管理和线程独占区和线程共享区

    一.内存管理 二.线程独占区之程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里,字节 ...