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整除数组中 ...
随机推荐
- spring + spring mvc 使用 maven 编译出现异常
异常如下: [INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------- ...
- codeforces396C
On Changing Tree CodeForces - 396C You are given a rooted tree consisting of n vertices numbered fro ...
- 正则re.complie作用
封装一个原本重复使用的正则表达式 prog = re.compile(pattern) result = prog.match(string)
- QQ 为什么以 UDP 协议为主,以 TCP 协议为辅?
QQ既有UDP也有TCP!不管UDP还是TCP,最终登陆成功之后,QQ都会有一个TCP连接来保持在线状态.这个TCP连接的远程端口一般是80,采用UDP方式登陆的时候,端口是8000. UDP协议是无 ...
- AOP 与 Spring中AOP使用(下)
AOP通知类型 前置通知 在目标方法执行之前进行操作 UserDao.java public class UserDao { public void add(){ System.out.println ...
- java定时案例
好久没写笔记了,变懒了! java定时运行的三个案例: 一, 通过sleep方法来达到定时任务的效果 public class testTime { public static void main(S ...
- AT1357 n^p mod m(洛谷)
题意翻译 求 n^p mod m 的值 输入格式 一行,为整数 n,m,p(注意顺序) 输出格式 一行,为 n^p mod m 的值 数据说明 对于100%的数据 1≤n,m≤10^91≤n,m≤10 ...
- SSM基于Token的登录认证
1.什么是token token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识. 当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上 ...
- mysqlcheck修复工具
mysqlcheck工具可以检查.修复.优化和分析MyISAM引擎的表,实际上是集成了Mysql中的check.repair.analyze.tmpimize的功能. mysqlcheck共军存在于m ...
- Mysql的安全配置向导命令mysql_secure_installation
mysql_secure_installation安全配置向导 [root@youxi1 ~]# mysql_secure_installation Securing the MySQL server ...