传送门

参考资料:

  [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(树状数组求冒泡排序循环次数加强版)的更多相关文章

  1. 洛谷 P4378 [USACO18OPEN]Out of Sorts S(树状数组求冒泡排序循环次数)

    传送门:Problem P4378 https://www.cnblogs.com/violet-acmer/p/9833502.html 要回宿舍休息了,题解明天再补吧. 题解: 定义一数组 a[m ...

  2. 洛谷 P1908 逆序对 Label:归并排序||树状数组 不懂

    题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...

  3. 【洛谷P1972】HH的项链 离线+树状数组

    题目大意:静态查询序列区间颜色数. 题解:对于一个查询区间 [l , r] ,若有两个相同颜色的点在这个区间中,则总是取下标靠近端点 r 的颜色计入答案贡献.对于每个下标,记录下在这个下标之前,且距离 ...

  4. 洛谷 P3616 富金森林公园题解(树状数组)

    P3616 富金森林公园 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积水也有 ...

  5. 洛谷P3312 [SDOI2014]数表(莫比乌斯反演+树状数组)

    传送门 不考虑$a$的影响 设$f(i)$为$i$的约数和 $$ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^nf(gcd(i,j))$$ $$=\sum\limi ...

  6. 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...

  7. 洛谷P3810-陌上开花(三维偏序, CDQ, 树状数组)

    链接: https://www.luogu.org/problem/P3810#submit 题意: 一个元素三个属性, x, y, z, 给定求f(b) = {ax <= bx, ay < ...

  8. 洛谷 P1972 [SDOI2009]HH的项链(树状数组,离线)

    传送门 解题思路 因为是求区间的不同种类数,所以我们用树状数组(貌似并没有什么直接联系) (...表示到) 还是和原来一样,用s[i]来表示a[i-lowbit(i)]...a[i]的种类数. 因为有 ...

  9. 洛谷P1972 [SDOI2009]HH的项链(树状数组)

    题目链接: https://www.luogu.org/problemnew/show/P1972 题目描述: HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后 ...

随机推荐

  1. 自动化批量管理工具salt-ssh - 运维小结

    根据以往运维工作中操作经验来说,当管理上百台上千台服务器时,选择一款批量操作工具是及其有必要的.早期习惯于在ssh信任关系的前提下做for;do;done循环语句的批量操作,后来逐渐趋于使用批量工具操 ...

  2. A. Make a triangle!

    题意 给你三条边a,b,c问使得构成三角形,需要增加的最少长度是多少 思路 数学了啦 代码 #include<bits/stdc++.h> using namespace std; #de ...

  3. 虚拟机Linux(centos)系统能ping通主机,主机无法ping通Linux解决方案

    本文引用:https://blog.csdn.net/clean_water/article/details/53023308 三个步骤: 第一步:虚拟机网络连接方式选择Nat 第二步.关闭liunx ...

  4. Java基础知识中的注意事项

    设置Java的相关路径,举例: JAVA_HOME  -->   C:\Program Files\Java\jdk1.8.0_191 Path --->   C:\Program Fil ...

  5. PAT 1071 小赌怡情

    https://pintia.cn/problem-sets/994805260223102976/problems/994805264312549376 常言道“小赌怡情”.这是一个很简单的小游戏: ...

  6. MySQL: Connection Refused,调整 mysql.ini中的 max_connections

    连接相同的结构的MySQL数据库,一套库Tomcat启动正常,另一套库一直报Connection Refused. 可以断定是连接数太小了.查找mysql.ini中的 max_connections, ...

  7. 常用的查询DOM的方法

    查询body的方法=========== document.body // document.getElementsTagname("body")[0]; 查询html的方法=== ...

  8. C#微信公众号开发入门教程

    首先打开开发文档: 微信公众号开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 一.创建测试账号 可以先申请一个开发者测试账号

  9. Node 连接池pool

    //1:加载相应的模块 http url fs mysqlconst http = require("http");const url = require("url&qu ...

  10. python 3以上版本使用pickle.load读取文件报UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 6

    python 3以上版本使用pickle.load读取文件报UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 6 ...