[树状数组] Jzoj P3462 休息

Description

休息的时候,可以放松放松浑身的肌肉,打扫打扫卫生,感觉很舒服。在某一天,某LMZ 开始整理他那书架。已知他的书有n 本,从左到右按顺序排列。他想把书从矮到高排好序,而每一本书都有一个独一无二的高度Hi。他排序的方法是:每一次将所有的书划分为尽量少的连续部分,使得每一部分的书的高度都是单调下降,然后将其中所有不少于2 本书的区间全部翻转。重复执行以上操作,最后使得书的高度全部单调上升。可是毕竟是休息时间,LMZ 不想花太多时间在给书排序这种事上面。因此他划分并翻转完第一次书之后,他想计算,他一共执行了多少次翻转操作才能把所有的书排好序。LMZ 惊奇地发现,第一次排序之前,他第一次划分出来的所有区间的长度都是偶数。

Input

第一行一个正整数n, 为书的总数。

接下来一行n个数,第i个正整数Hi,为第i 本书的高度。

Output

仅一个整数,为LMZ 需要做的翻转操作的次数。

Sample Input

6
5 3 2 1 6 4

Sample Output

3
【样例解释】
第一次划分之后,翻转(5,3,2,1),(6,4)。之后,书的高度为1 2 3 5 4 6,然后便是翻转(5,4)即可。
 

Data Constraint

对于10%的数据:n<=50

对于40%的数据:n<=3000

对于100%的数据:1<=n<=100000, 1<=Hi<=n

题解

  • 对于序列进行第一次划分后,以后的每次翻转都是两个数
  • 为什么呢?
  • 因为对于第一次翻转后会形成这样的一个序列:a1、a2...ai、b1、b2...bj、c1、c2...ck...
  • 会形成若干个连续上升序列
  • 考虑相邻的两个部分,ai与b1相邻
  • 如果ai<b1的话,也就是说明这两个序列都是严格上升的,如果不是的话,就要进行翻转
  • 因为ai-1<ai、b1<b2
  • 所以以后的每次翻转都只用翻转两个相邻的逆序对
  • 求逆序对可以用树状数组,那么对于第一次翻转,直接模拟可以得到

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 const long long inf=1000000000;
 6 long long n,a[100010],mx,l,sum[100010];
 7 long long ans;
 8 long long getsum(long long x)
 9 {
10     long long num=0;
11     while (x>0)
12     {
13         num+=sum[x];
14         x-=x&-x;
15     }
16     return num;
17 }
18 void update(long long x)
19 {
20     while (x<=n)
21     {
22         sum[x]++;
23         x+=x&-x;
24     }
25 }
26 void swap(long long l,long long r)
27 {
28     long long b[100010];
29     for (long long i=l;i<=r;i++) b[i]=a[r-i+l];
30     for (long long i=l;i<=r;i++) a[i]=b[i];
31 }
32 int main()
33 {
34     scanf("%lld",&n);
35     for (long long i=1;i<=n;i++) scanf("%lld",&a[i]);
36     mx=inf; l=1;
37     for (long long i=1;i<=n;i++)
38     {
39         if (mx<a[i])
40         {
41             if (l!=i-1)
42             {
43                 ans++;
44                 swap(l,i-1);
45                 mx=a[i]; l=i;
46             }
47         }
48         else  mx=a[i];
49     }
50     if (l<n) swap(l,n),ans++;
51     for (long long i=n;i>=1;i--)
52     {
53         ans+=getsum(a[i]);
54         update(a[i]);
55     }
56     printf("%lld",ans);
57     return 0;
58 }

原文地址:https://www.cnblogs.com/Comfortable/p/9337924.html

时间: 2024-08-30 06:16:58

[树状数组] Jzoj P3462 休息的相关文章

[CDQ分治][树状数组][树套树] Jzoj P3197 K大数查询

Description 有n 个位置和m 个操作.操作有两种,每次操作如果是1 a b c 的形式,表示往第a 个位置到第b 个位置每个位置加入一个数c.如果操作形如2 a b c 的形式,表示询问从第a 个位置到第b 个位置,第c 大的数是多少. Input 在输入文件sequence.in 中,第一行两个数n,m.意义如题目描述.接下来m 行每行形如1 a b c 或者2 a b c 如题目描述. Output 在输出文件sequence.out 中,对于每个询问回答k 大数是多少. Sam

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

(POJ 3067) Japan (慢慢熟悉的树状数组)

Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29295   Accepted: 7902 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coas

【二维树状数组】See you~

https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A x y n1 :给格点(x,y)的值加n1 D x y n1: 给格点(x,y)的值减n1,如果现在格点的值不够n1,把格点置0 M x1 y1 x2 y2:(x1,y1)移动给(x2,y2)n1个 S x1 y1 x2 y2 查询子矩阵的和 [思路] 当然是二维树状数组 但是一定要注意:lowbi

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击

CF 313 DIV2 B 树状数组

http://codeforces.com/contest/313/problem/B 题目大意 给一个区间,问你这个区间里面有几个连续相同的字符. 思路: 表示个人用树状数组来写的...了解了树状数组的本质就行了. 当然用sum[r]-sum[l]也是可以的

Hdu5032 极角排序+树状数组

题目链接 思路:参考了题解.对询问进行极角排序,然后用树状数组维护一下前缀和即可. /* ID: onlyazh1 LANG: C++ TASK: test */ #include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long ll; const int maxn=1010; const int maxm=10

Curious Robin Hood(树状数组+线段树)

1112 - Curious Robin Hood    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another tri

【初识——树状数组】 区间求最值

说树状数组其实是一个索引表,但是是一个特殊的,树状的索引表,它利用了二进制的一些特性. 就区间求和的要求来说: 首先我们用a[]数组来存储原始数据.然后在a[]之上构造c[]数组来作为树状数组. 如图 这个图表示,当i为奇数时,c[i]中保存的都是a[i]本身.然后,c[2]中保存了a[1], a[2],共2个,c[4]中保存的是a[1], a[2], a[3], a[4],c[6]又是保存两个,c[5]和c[6].c[8]保存8个,c[1], c[2], c[3], c[4], c[5], c