「UVA10810」Ultra-QuickSort 解题报告
2024-09-05 03:49:49
题面
看不懂?!
大概的意思就是:
给出一个长度为n的序列,然后每次只能交换相邻的两个数,问最小需要几次使序列**严格上升 **
不断读入n,直到n=0结束
思路:
交换相邻的两个数,这不就类似冒泡排序吗?但是n<500000
算了吧,我回去颓A+B
于是我们就发现用冒泡排序直接计算次数是行不通的
但我们要知道:
冒泡排序的交换次数就是序列的逆序对数!!!
所以——就简单了吧~
如何求逆序对?
1、归并排序
思想是分治法
不断划分为两小段
然后依次由小序列合并为大序列,同时求出逆序数
2、树状数组
因为树状数组的修改查询是log级的所以可以使用(前缀和的方法),没学的建议先去学习一下,不是很难
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
int x,i;
}a[500010];
int n;
int b[500010];
int f[500010];
ll ans;
int read()
{
int s=0;
char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
{
s=(s<<1)+(s<<3)+c-'0';
c=getchar();
}
return s;
}
void update(int x)//修改
{
for(;x<=n;x+=x&(-x))
f[x]++;
return;
}
ll sum(int x)//求前缀和
{
ll res=0;
for(;x;x-=x&(-x))
res+=f[x];
return res;
}
bool cmp(node a,node b)
{
return a.x>b.x;
}
int main()
{
int i,j;
n=read();
while(n)
{
ans=0;
memset(f,0,sizeof(f));
for(i=1;i<=n;i++)
{
a[i].x=read();
a[i].i=i;
}
sort(a+1,a+n+1,cmp);
for(i=1;i<=n;i++)//先hash一下,按数值给其标记,方便后面求逆序对
b[a[i].i]=i;
for(i=1;i<=n;i++)
{
update(b[i]);//一步一做
ans+=sum(b[i]-1);
}
printf("%lld\n",ans);
n=read();
}
return 0;
}
最新文章
- Win10 字体模糊解决(DPI缩放禁用),设置默认输入法英文
- html drag api 在firefox 下 拖动出现新窗口的解决办法
- cocoapods安装出错问题
- Oracle体系中各个组件的含义
- Linux上如何执行java程序
- MVC 支持同名路由,不同命名空间
- 带给你灵感:30个超棒的 SVG 动画展示【下篇】
- NSValue&;NSNumber
- google-breakpad
- C++ VS2010 声明没有存储类或类型说明符
- C# 接口的隐式与显示实现【转】
- typeof + instanceof+toString+constructor什么推理javascript数据类型
- Echarts数据可视化series-heatmap热力图,开发全解+完美注释
- UWP更改标题栏颜色
- Robot Framework 环境安装(一)
- memcache讲解和在.net中初使用
- pyspider源码解读--调度器scheduler.py
- 关于 百度 Ueditor (在chrome浏览器) 上传图片时 打开文件夹的延迟问题
- 03、 forms组件
- 系统导出数据到excel,数据量过大(大约10W)条,导致服务器 cpu 100%解决方法