洛谷 P4375 [USACO18OPEN]Out of Sorts G(树状数组求冒泡排序循环次数加强版)
参考资料:
[1]:https://www.cnblogs.com/Miracevin/p/9662350.html
[2]:https://blog.csdn.net/lengxuenong/article/details/80482202?utm_source=blogxgwz1
今天已经理解了一晚上了,还是处于懵懵懂懂的状态,明天在肝一天,一定要将自己理解的题解写出来,哇咔咔!
•题解
定义数组 a;
先将含有 n 个元素的数组 a 离散化,则离散化后的 n 个元素对应 1~n 的某个排列,而我们所要求的就是将离散化后的排列变为 1,2,3,...,n 所需的循环次数。
对于位置 i ,在这个双向排序过程中,每次 while( ) 循环会把一个 i 之前的大于 i 的数移到 i 后面,并且把一个 i 之后小于 i 的数移到 i 的前面。
for : i 1 to N
我们可以对于所有的位置 i ,找到[1,i]范围内比 i 小的数的个数 s,i-s 就是 i 位置把小于 i 的放在 i 位置前面,大于 i 的放在 i 位置后面的循环次数。
•对红色字体的理解
冒泡排序,通过交换相邻两数最终使得数组有序;
对于每个位置 i ,如果比 i 大的数都交换到 i 位置之后,比 i 小的数都交换到 i 位置之前;
那么,等结束最后一个 i 位置的时候,冒泡排序也就结束了,此时数组也就是有序的。
因此,对于此题的双向循环,每次判断当前位置 i 需要通过多少次while( )循环才能使得:
比 i 大的数都交换到 i 位置之后,比 i 小的数都交换到 i 位置之前;
因此,只需要求出 [1,i] 位置上比 i 大的数的个数,输出最大的那个即是答案;
•Code
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x))
const int maxn=1e5+; int n;
struct Node
{
int val;
int id;
int newVal;
}a[maxn];
//==================BIT=====================
int bit[maxn];
void Add(int x)
{
while(x <= n)
{
bit[x]++;
x += lowbit(x);
}
}
int Sum(int x)
{
int sum=;
while(x > )
{
sum += bit[x];
x -= lowbit(x);
}
return sum;
}
//=======================================
bool cmp(Node _a,Node _b) {//注意,如果val相同,初始编号 id 小的在前
return _a.val < _b.val || (_a.val == _b.val && _a.id < _b.id);
}
bool cmp1(Node _a,Node _b){//将数组恢复到刚开始输入时的状态
return _a.id < _b.id;
}
void Solve()
{
sort(a+,a+n+,cmp);//离散化
for(int i=;i <= n;++i)
a[i].newVal=i;//存储离散化后的值
sort(a+,a+n+,cmp1);
int res=;
for(int i=;i <= n;++i)
{
Add(a[i].newVal);
res=max(res,i-Sum(i));//询问每个位置,找到所需的最大的循环次数
}
printf("%d\n",res);
}
int main()
{
scanf("%d",&n);
for(int i=;i <= n;++i)
scanf("%d",&a[i].val),a[i].id=i;
Solve();
}
•初始疑惑
将 i 之前的大于 i 的数归位,貌似只用到了问题中的第一个for( ),而并没有用第二个 for( )循环啊;
那为什么 i-s 就是 i 位置把小于 i 的放在 i 位置前面,大于 i 的放在 i 位置后面的循环次数呢?
我的理解:
①如果将 [1,i] 位置中的大于 i 的数全部移到 i 位置后,[i+1,n]位置中的数肯定全部大于 i;
如果 [i+1,n] 位置存在小于 i 的数,那,[1,i]中肯定存在大于 i 的数,不然,怎么交换呢?
这样的话,[1,i]位置中大于 i 的数就没有全部移到 i 位置后,与条件①矛盾;
所以条件①成立;
分割线:2019.7.17
•感想
当初理解了好长时间的东西到如今成了自然而然地事;
•Code
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&-x)
const int maxn=1e5+; int n;
struct Data
{
int v;
int id;
int newV;
}data[maxn];
struct BIT
{
int bit[maxn];
void Init()
{
memset(bit,,sizeof(bit));
}
void add(int t)
{
while(t < maxn)
{
bit[t]++;
t += lowbit(t);
}
}
int Sum(int t)
{
int sum=;
while(t > )
{
sum += bit[t];
t -= lowbit(t);
}
return sum;
}
}_bit; ///树状数组求逆序对时,v相同的一定要让编号小的在前
bool cmp1(Data a,Data b)
{
if(a.v != b.v)
return a.v < b.v;
return a.id < b.id;
}
bool cmp2(Data a,Data b)
{
return a.id < b.id;
}
int Solve()
{
sort(data+,data+n+,cmp1);
for(int i=;i <= n;++i)
data[i].newV=i;
sort(data+,data+n+,cmp2); _bit.Init();
int ans=;
for(int i=;i <= n;++i)
{
_bit.add(data[i].newV);
ans=max(ans,i-_bit.Sum(i));
} return ans;
}
int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
scanf("%d",&n);
for(int i=;i <= n;++i)
{
scanf("%d",&data[i].v);
data[i].id=i;
}
printf("%d\n",Solve()); return ;
}
洛谷 P4375 [USACO18OPEN]Out of Sorts G(树状数组求冒泡排序循环次数加强版)的更多相关文章
- 洛谷 P4378 [USACO18OPEN]Out of Sorts S(树状数组求冒泡排序循环次数)
传送门:Problem P4378 https://www.cnblogs.com/violet-acmer/p/9833502.html 要回宿舍休息了,题解明天再补吧. 题解: 定义一数组 a[m ...
- 洛谷 P1908 逆序对 Label:归并排序||树状数组 不懂
题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...
- 【洛谷P1972】HH的项链 离线+树状数组
题目大意:静态查询序列区间颜色数. 题解:对于一个查询区间 [l , r] ,若有两个相同颜色的点在这个区间中,则总是取下标靠近端点 r 的颜色计入答案贡献.对于每个下标,记录下在这个下标之前,且距离 ...
- 洛谷 P3616 富金森林公园题解(树状数组)
P3616 富金森林公园 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积水也有 ...
- 洛谷P3312 [SDOI2014]数表(莫比乌斯反演+树状数组)
传送门 不考虑$a$的影响 设$f(i)$为$i$的约数和 $$ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^nf(gcd(i,j))$$ $$=\sum\limi ...
- 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)
传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...
- 洛谷P3810-陌上开花(三维偏序, CDQ, 树状数组)
链接: https://www.luogu.org/problem/P3810#submit 题意: 一个元素三个属性, x, y, z, 给定求f(b) = {ax <= bx, ay < ...
- 洛谷 P1972 [SDOI2009]HH的项链(树状数组,离线)
传送门 解题思路 因为是求区间的不同种类数,所以我们用树状数组(貌似并没有什么直接联系) (...表示到) 还是和原来一样,用s[i]来表示a[i-lowbit(i)]...a[i]的种类数. 因为有 ...
- 洛谷P1972 [SDOI2009]HH的项链(树状数组)
题目链接: https://www.luogu.org/problemnew/show/P1972 题目描述: HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后 ...
随机推荐
- C_数据结构_链式二叉树
# include <stdio.h> # include <malloc.h> struct BTNode { int data; struct BTNode * pLchi ...
- 算法模板学习专栏之总览(会慢慢陆续更新ing)
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/7495310.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- PHP输入流 php://input 相关【转】
为什么xml_rpc服务端读取数据都是通过file_get_contents(‘php://input', ‘r').而不是从$_POST中读取,正是因为xml_rpc数据规格是xml,它的Conte ...
- 《Linux内核设计与实现》第七章读书笔记
第七章.中断和中断处理 7.1中断 中断使得硬件得以发出通知给处理器.中断随时可以产生,内核随时可能因为新来到的中断而被打断. 不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标志.操作系统给 ...
- Linux内核分析 读书笔记 (第三章)
第三章 进程管理 3.1 进程 1.进程: 进程就是处于执行期的程序. 进程就是正在执行的程序代码的实时结果. 进程是处于执行期的程序以及相关的资源的总称. 进程包括代码段和其他资源. 2.线程:执行 ...
- Linux实践三:程序破解
一.汇编指令机器码 二.反汇编与十六进制编程器 三.可执行文件的基本格式 hexdump -x login 用16进制数字显示login内容 objdump -x login 显示login中各个段以 ...
- Open Source CRM
https://www.odoo.com/zh_CN/page/crm 试用: https://none53.odoo.com/web#home https://none.mypscloud.com/ ...
- WIN10 评估版 查看过期时间
命令行运行winver,弹出的窗口显示过期时间,如 下图: 又可以再用一段时间教育版了,本机预装的的家庭版序列号,还没法从教育版降级到家庭版,可悲吧(win7时代就不允许从高级降低到低级用啊)
- mongoose 入门基本操作
简介 Mongoose是在node.js异步环境下对mongodb进行便捷操作的对象模型工具 那么要使用它,首先你得装上node.js和mongodb,关于mongodb的安装和操作介绍可以参考:ht ...
- pandas获取当前时间
datetime.now()用于获取当前的日期和时间 print pd.datetime.now() #encoding:utf8 import pandas as pd print("(p ...