FZU2018级算法第二次作业 2.10 逆序数(权值线段树)
题目:
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 逆序数(权值线段树)的更多相关文章
- [NOIP2015模拟10.27] [JZOJ4270] 魔道研究 解题报告(动态开点+权值线段树上二分)
Description “我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力.”——<The Grimoire of Marisa>雾雨魔理 ...
- FZU2018级算法第五次作业 m_sort(归并排序或线段树求逆序对)
首先对某人在未经冰少允许情况下登录冰少账号原模原样复制其代码并且直接提交的赤裸裸剽窃行为,并且最终被评为优秀作业提出抗议! 题目大意: 给一个数组含n个数(1<=n<=5e5),求使用冒泡 ...
- 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 ...
- FZU2018级算法第一次作业 1.1fibonacci (矩阵快速幂)
题目 Winder最近在学习fibonacci 数列的相关知识.我们都知道fibonacci数列的递推公式是F(n)=F(n-1)+F(n-2)(n>=2 且n 为整数). Winder想知道的 ...
- FZU2018级算法第五次作业 missile(排序+枚举)
在解题报告之前,首先对同一次作业中另外一题(求逆序对)某人在未经冰少允许情况下,擅自登录冰少账号,原模原样剽窃冰少代码,并且最终还被评为优秀作业的行为表示严正抗议! 题目大意: 二维平面上给出 n 个 ...
- 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 题目分析: 假设目 ...
- js第二次作业——2019.10.16
第一题:完成省城市的三级联动(包括湖南省),附代码和效果图. 1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 </head> ...
- 2016级算法第二次上机-G.ModricWang's Real QuickSort
873 思路 这是一道非常基础的题,目的是帮助大家回顾快排相关的知识.大家完成此题之后应该就对快排有比较深刻的印象了. 对于整个快排的流程,题目描述中已经给了清晰完整的伪代码.需要自己加工的部分就是, ...
- 2016级算法第二次上机-F.ModricWang's Number Theory II
891 ModricWang's Number Theory II 思路 使得序列的最大公约数不为1,就是大于等于2,就是找到一个大于等于2的数,它能够整除序列中的所有数. 考虑使得一个数d整除数组中 ...
随机推荐
- ubuntu ukylin wineqq 登录时提示:您的号码暂时不能使用低版本的qq
ubuntu ukylin wineqq 登录时提示:您的号码暂时不能使用低版本的qq,而有的qq号登录没有问题. 优麒麟官网上下载的qqwine安装包,解压后安装三个deb包. 郁闷了一下午,都想装 ...
- 基于Shiro的登录功能 设计思路
认证流程 Shiro的认证流程可以看作是个“有窗户黑盒”, 整个流程都有框架控制,对外的入口只有subject.login(token);,这代表“黑盒” 流程中的每一个组件,都可以使用Spring ...
- 使用MockMVC与Junit进行单体测试
1.pom.xml追加 junit spring-test 2.测试共通类 @ContextConfiguration(locations = { "classpath:springfram ...
- P2822 组合数问题——巧用前缀和
P2822 组合数问题 求的是C(i,j)有多少个是k的倍数: 首先,求组合数是有技巧的, 用杨辉三角求组合数,爽的一批: 但是,这样只能得90分,两个点T了: 因为k是不变的,我们可以用前缀和的思想 ...
- 通过Confulence API统计用户文档贡献量
Confulence提供了非常清晰的RESTful API,直接使用API比confluence_python_cli这个库更方便. 参考文档:https://developer.atlassian. ...
- javascript中的contains方法和compareDocumentPosition方法
IE有许多好用的方法,后来都被其他浏览器抄袭了,比如这个contains方法.如果A元素包含B元素,则返回true,否则false.唯一不支持这个方法的是IE的死对头firefox.不过火狐支持com ...
- Matlab注释的几个方法
Matlab最简单的注释当然是 %x= %这是注释,无法运行 x= %结果为2 然而%只能注释一行,如何注释更加快捷简便地注释多行呢? %{ .这就是传说中的多行注释 .成功! %} 经常需要调试程序 ...
- JVM | JVM体系结构认知
虚拟机 何为虚拟机呢?虚拟机是模拟执行某种指令集体系结构(ISA)的软件,是对操作系统和硬件的一种抽象.其软件模型如下图所示: 计算机系统的这种抽象类似于面向对象编程(OOP)中的针对接口编程泛型(或 ...
- 阿里PB级Kubernetes日志平台建设实践
干货分享 | 阿里PB级Kubernetes日志平台建设实践https://www.infoq.cn/article/HiIxh-8o0Lm4b3DWKvph 日志最主要的采集工具是 Agent,在 ...
- utf-8的中文是一个字符占几个字节
utf-8的中文是一个字符占几个字节 英文字母和中文汉字在不同字符集编码下的字节数英文字母:·字节数 : 1;编码:GB2312 字节数 : 1;编码:GBK 字节数 : 1;编码:GB18030 字 ...