洛谷 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 相信不同的贝壳会带来好运,所以每次散步完后 ...
随机推荐
- 详解centos7配置本地yum源的方法
近在使用虚拟机时遇到一些麻烦,因为公司内部有网络管理,所以vm连接不上外网,yum无法安装软件,怎么解决呢?–使用iso做本地yum源,可以解决大部份的包安装. vm安装的是centos7. 1.挂载 ...
- svg矢量图在flex布局中样式扭曲的问题
问题机型 小米5 华为nova 其他未知的可能机型 问题描述 利用flex 布局的一行中, 左一样式: -webkit-box-flex: 0; flex: 0 1 auto; 左二样式: -webk ...
- MySQL的启动程序
1.mysqld: mysql server [root@test bin]# ./mysqld --user=mysql & [root@test bin]# ps ...
- Echarts学习求教
有没有人用过百度的Echarts?刚开始接触,下面这段代码怎么理解啊,新手求指教: myChart.showLoading();$.get('data/asset/data/les-miserable ...
- 北航学堂Android客户端Beta阶段发布说明
在从学姐那里拿到服务接口的代码最终连通服务器之后,经过我们团队的努力,终于把前后端融合生成了我们目前的版本, 因为我们在Alpha阶段网络连接部分是一直没有搞定的,所以这个版本其实并不算是真正的Bet ...
- JAVA常用工具类汇总
一.功能方法目录清单: 1.getString(String sSource)的功能是判断参数是否为空,为空返回"",否则返回其值: 2.getString(int iSource ...
- Maven相关问题解决.docx
1. 问题 2. 原因 出现.lastUpdated结尾的文件的原因:由于网络原因没有将Maven的依赖下载完整,导致. 解决方案: 1.删除所有以.lastUpdate结尾的文件 a)1.切换到ma ...
- FreeMarker boolean Issue
FreeMarker template error:Can't convert boolean to string automatically, because the "boolean_f ...
- Java 中文 乱码问题
Java平台遇到的两类问题: 1.源代码中文乱码问题: a.Java文件,中文乱码,配置IDE的Preference的编码格式,总有一款适合你. b.HTML(JSP.....)文件,中文乱码,添加并 ...
- centos7 tar.xz格式文件的解压方法
现在很多找到的软件都是tar.xz的格式的,xz 是一个使用 LZMA压缩算法的无损数据压缩文件格式. 和gzip与bzip2一样,同样支持多文件压缩,但是约定不能将多于一个的目标文件压缩进同一个档案 ...