官方题解:https://media.hihocoder.com/contests/challenge34/tutorials-previewed.pdf

题目链接:http://hihocoder.com/problemset/problem/1781

题意问对于给定序列A,是否存在一个整数k, 使得A冒泡k轮后变成序列B.

这题一种做法是像官方题解一样写个计算区间最值的数据结构。

而我是另一种做法,通过的逆序数 来判断A怎样能变化到B。

例子

首先我举一个例子:

对于序列  A

8 7 5 1 9 2 6 4 3

其每个位置的逆序数是:

0 1 2 3 0 4 3 5 6       (*)

接着对A冒泡一轮,得到:

7 5 1 8 2 6 4 3 9

这时每个位置的逆序数是:

0 1 2 0 3 2 4 5 0      (**)

那么序列(*)和序列(**) 直接有啥联系呢?

(**)=(*)每个数减-1,并向左平移一格 ,且最多减到0.

证明

现在来证明,每冒泡一轮 所有位置的逆序数-1,并向左移一格。

引理1:对于每轮冒泡排序,若一个位置的前面存在比他大的数,  则他一定会他前面的某个比他大的数进行有且仅有一次交换

这个引理大家自已脑补一下,应该很容易理解是对的。

引理2:若一个位置的前面存在比他大的数,则个位置的逆序数大于0

这个废话,我就不解释了。

证:因为任意一个逆序大于1位置,都与比他大的数交换一次,交换后首先逆序数必然减一,其次,交换后为位置肯定前移1格。 故结论成立。

解题思路

有了这个规律,显然我可以直接O(n)求出任意一轮A的逆序数 与B比较。

再利用【逆序数和】每轮的都会递减的单调性。就可以用二分比较逆序数和的方式,在O(n logn)时间定位b.

或者做一个O(n)预处理,算出n-1轮中,每轮的逆序数和,这样可以把查询的时间复杂度降低至O(n)

当然因为还要对数据进行O(n logn)离散化和求逆序数的原因,所以无论你写哪种最终复杂度都是O(n logn)。

 #include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<stack>
#include<math.h>
using namespace std;
#define lowbit(x) (x&(-x))
int a[],b[];
int s1[],s2[];
int c[];
int N=;
int cot[];
int getsum(int x)
{
int sum=;
while(x)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
void add(int x)
{
while(x<=N)
{
c[x]++;
x+=lowbit(x);
}
}
vector<int>que;
int getid(int x)
{
return lower_bound(que.begin(),que.end(),x)-que.begin()+;
}
void cal(int n,int a[],int ans[])
{
int i;
memset(c,,sizeof(c));
for(i=; i<=n; i++)
{
ans[i]=(i-)-getsum(a[i]);
add(a[i]);
}
}
int main()
{
int i,j,t,n,x,y,k,op,q;
long long m;
// freopen("1.in","r",stdin);
//freopen("2.out","w",stdout);
scanf("%d",&t);
for(int cas=; cas<=t; cas++)
{
scanf("%d",&n);
memset(s1,,sizeof(s1));
memset(cot,,sizeof(cot));
que.clear();
for(i=; i<=n; i++)
{
scanf("%d",&a[i]);
que.push_back(a[i]);
}
for(i=; i<=n; i++)
{
scanf("%d",&b[i]);
que.push_back(b[i]);
}
sort(que.begin(),que.end());
m=unique(que.begin(),que.end())-que.begin();
que.resize(m);
int ans=-;
for(i=; i<=n; i++)
{
a[i]=getid(a[i]);
b[i]=getid(b[i]);
}
cal(n,a,s1);
cal(n,b,s2);
long long sum=;
k=;
for(i=; i<=n; i++)
{
cot[s1[i]]++;
k=max(s1[i],k);
sum+=s2[i];
printf("%d ",s1[i]);
}
m=;
for(i=k+; i>; i--)
{
m=m+cot[i];
sum-=m;
if(sum<=)
{
break;
}
}
if(sum==)
{
i--;
for(j=; j<=n; j++)
{
if(max(s1[j+i]-i,)!=s2[j])
{
break;
}
}
if(j>n)
{
sort(a+,a+n+);
sort(b+,b+n+);
for(j=; j<=n; j++)
{
if(a[j]!=b[j])
{
break;
}
}
if(j>n)
{
ans=i;
}
}
}
printf("Case #%d: %d\n",cas,ans);
}
return ; }

AC代码

hihoCoder挑战赛34 B题(快速求第k轮冒泡排序的结果)的更多相关文章

  1. hihoCoder挑战赛1 毁灭者问题

    题目链接:http://hihocoder.com/problemset/problem/1034 数据结构题,由于每个魔法单位有着不同的回复速度和上限,所以不能根据吸收时间点进行查询和更新.但是如果 ...

  2. hihoCoder挑战赛23

    hihoCoder挑战赛23 A.Emulator 题意 给一张图,有\(N(N \le 300)\)个点, 给出任意两点之间的最短路. 求最多可以去掉多少条边,使得任意两点的最短路长度不变. 思路 ...

  3. 快速求幂(Quick Exponentiation)

    接触ACM没几天,向各路大神求教,听说ACM主要是研究算法,所以便开始了苦逼的算法学习之路.话不多说,RT所示,学习快速求幂. 在头文件<math.h>或是<cmath>中,d ...

  4. NYOJ--102--次方求模(快速求幂取模)

    次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 求a的b次方对c取余的值   输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一 ...

  5. poj 2001:Shortest Prefixes(字典树,经典题,求最短唯一前缀)

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 12731   Accepted: 544 ...

  6. poj 1004:Financial Management(水题,求平均数)

    Financial Management Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 126087   Accepted: ...

  7. 快速求n的质因子(数论)

    快速求n的质因子 如何尽快地求出n的质因子呢?我们这里又涉及两个好的算法了! 第一个:用于每次只能求出一个数的质因子,适用于题目中给的n的个数不是很多,但是n又特别大的 #include<std ...

  8. 阿里聚安全攻防挑战赛第三题Android PwnMe解题思路

    阿里聚安全攻防挑战赛第三题Android PwnMe解题思路 大家在聚安全挑战赛正式赛第三题中,遇到android app 远程控制的题目.我们今天带你一探究竟,如何攻破这道题目. 一.题目 购物应用 ...

  9. 【GDOI 2011 DAY2 T3】零什么的最讨厌了 (快速求阶乘、中国剩余定理)

    问题描述: 林记在做数学习题的时候,经常遇到这种情况:苦思冥想了很久终于把问题解出来,结果发现答案是0,久而久之林记在得到习题答案是0的时候就没有了做出一道难题的成就感.于是林记决定:以后出题,答案一 ...

随机推荐

  1. 裸机——I2C

    网上搜了些资料,碍于智商和基础,看不懂, 只有将S5PV210 数据手册关于I2C的部分,翻译记录下,留到以后用. 1.OVERVIEW The S5PV210 RISC microprocessor ...

  2. C# 禁止在textBox输入框输入非法字符

    首先添加下面代码 //禁止在textBox输入框输入非法字符 private void keypressed(Object o, KeyPressEventArgs e) { if (e.KeyCha ...

  3. Permute Digits 915C

    You are given two positive integer numbers a and b. Permute (change order) of the digits of a to con ...

  4. struct2 命名空间

    转自http://blog.csdn.net/carefree31441/article/details/4857546 使用Struts2,配置一切正常,使用常用tag也正常,但是在使用<s: ...

  5. 关于update 表名 set 字段1 = 值1 and 字段2 = 值2的执行结果说明

    技术交流群: 233513714 如果执行了以下的语句,则brand等于‘OPPO’条件所对应的数据不会做改变,但是sequence_brand列除brand = 'OPPO'之外的所有数据都会变为0 ...

  6. Go实现try-catch-finally机制

    前言 许多主流语言诸如:Java.Python都实现了try-catch-finally机制,而Go处理错误的方式却与前两种语言不同.关于Go处理异常的方式是好是坏仁者见仁智者见智,笔者还是更喜欢tr ...

  7. 剑指Offer - 九度1356 - 孩子们的游戏(圆圈中最后剩下的数)

    剑指Offer - 九度1356 - 孩子们的游戏(圆圈中最后剩下的数)2014-02-05 19:37 题目描述: 每年六一儿童节,JOBDU都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.H ...

  8. web前端开发总结(未完)

    由于我也是接触前端开发不久,所以呢,自己也会做点小功课,于是,我把前端能够用到的知识稍稍做了下总结,总结的不全面,以后会慢慢完善的! 移动前端开发基础 (总结----待完善)1.移动前端开发:简而言之 ...

  9. win7 64位如何共享XP上的打印机?

    这个问题看似很简单,但是一旦你遇到了,就会发觉不是想象的那么简单. 除了网上能搜到的一些设置之外,这里还有几个诀窍: 1.首先你必须准备你的打印机的64位驱动程序 2.你在win7上必须采用添加本地打 ...

  10. mac安装虚拟机VirtualBox,并在虚拟机上安装centos

    1. 首先从网页上https://www.virtualbox.org/wiki/Downloads下载VirtualBox-6.0.0-127566-OSXdmg文件.我一般把下载的文件放到/opt ...