Ultra-QuickSort (求逆序数+离散化处理)、Cows、Stars【树状数组】
一、Ultra-QuickSort(树状数组求逆序数)
Ultra-QuickSort
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 73943 | Accepted: 27692 |
Description
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
5
9
1
0
5
4
3
1
2
3
0
Sample Output
6
0
思路:
题目表达的很清楚,是想要求输入序列的逆序数(判断序列中的每一位,在之前的数中比该位表示的数大的个数的总和)
例如:
9 1 0 5 4 这个序列
在1前面比1大的有1个 (9) 所以 ans+=1;
在0前面比0大的有两个 (9、1)所以 ans+=2;
同理 ans+=1;ans+=2;
所以ans=6即表示序列的逆序数。
求逆序数的方法如下(暴力):
** 还以上面的序列为例:9 1 0 5 4
给上面每个值按照位置编号从1~5
从第一位开始遍历:先将vis[9]=1;数字9看做位置序号;然后从1开始遍历vis[1]到vis[9]并求和 记录sum=getsum[9];
则 ans+=(i-getsum[9]); 此时i=1,getsum[9]=1(1是因为仅有vis[9]=1); 所以 ans+=(1-1);
往后过程同理;
暴力代码:
肯定会TLE但是可以使用树状数组优化求和过程使O(n²)的复杂度降为O(nlgn);
for(int i=1;i<=n;i++){
int t=i;vis[a[i]]=1; //整个过程相当于求i-getsum[a[i]];
for(int j=1;j<=a[i];j++){
if(vis[j]==1){
t--;
}
}
ans+=t;
}
**会遇到的问题:
从上面可以知道输入的9看做序号i 但如果9超过数组范围怎么办?
离散化处理:将输入的a[i] 从1开始排列到n 前提是n个数不能重复
例如上面 9 1 0 5 4
离散化结果为:5 2 1 4 3
离散化处理代码:
#include<stdio.h>
#include<algorithm>
using namespace std;
const int MAX=1e5;
struct node{
int count;
int num;
}edge[MAX+5];
bool cmp1(node a, node b)
{
return a.count<b.count;
}
bool cmp2(node a, node b)
{
return a.num<b.num;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&edge[i].count);
edge[i].num=i;
}
sort(edge+1,edge+n+1,cmp1); //按照count大小排序
for(int i=1;i<=n;i++){
edge[i].count=i; //给count重新赋值1~n
}
sort(edge+1,edge+n+1,cmp2); //按照num排序恢复最初大小关系
for(int i=1;i<=n;i++){
printf("%d ",edge[i].count);
}
printf("\n");
return 0;
}
AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAX=5e5;
struct node{
LL i;
LL num;
}edge[MAX+5];
LL n;
LL vis[MAX+5];
bool cmp1(node a, node b)
{
return a.num<b.num;
}
bool cmp2(node a, node b)
{
return a.i<b.i;
}
void add(LL x,LL y)
{
for(LL i=x;i<=n;i+=i&(-i)){
vis[i]+=y;
}
}
LL getsum(LL x)
{
LL ans=0;
for(LL i=x;i>=1;i-=i&(-i)){
ans+=vis[i];
}
return ans;
}
int main()
{
while(~scanf("%lld",&n)&&n){
memset(vis,0,sizeof(vis));
for(LL i=1;i<=n;i++){
scanf("%lld",&edge[i].num);
edge[i].i=i;
}
sort(edge+1,edge+n+1,cmp1);
LL top=1;
for(LL i=1;i<=n;i++){
edge[i].num=top++;
}
sort(edge+1,edge+n+1,cmp2);
LL ans=0;
for(LL i=1;i<=n;i++){
LL t=i;
add(edge[i].num,1);
ans+=(t-getsum(edge[i].num));
}
printf("%lld\n",ans);
}
return 0;
}
二、Cows
Cows
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 23665 | Accepted: 7962 |
Description
Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.
Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John's N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].
But some cows are strong and some are weak. Given two cows: cowi and cowj, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cowi is stronger than cowj.
For each cow, how many cows are stronger than her? Farmer John needs your help!
Input
The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 105), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 105) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.
The end of the input contains a single 0.
Output
For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cowi.
Sample Input
3
1 2
0 3
3 4
0
Sample Output
1 0 0
Hint
Huge input and output,scanf and printf is recommended.
思路:
开始做这个题想到的也是暴力(看数据知道会TLE),后来换了思路但又感觉x和y没有关系 会不太好控制,就不知怎么办了
看了讲解:
先将y从大到小排列 这样就保证了后面输入的y值一定是比前面的要小 然后从1遍历数组vis求和便可以得到有多少个符合条件的 然后将所有数加起来便可以得到结果。但是也要注意数据范围是(0 <= S < E <= 105) 有0在里面就没办法使用树状数组求和所以add(x)的时候最好是add(x+1),同时sum(x) 变为 sum(x+1),这样就避免了那种情况。
代码也不是特别麻烦 还要注意while输入 每次使用数组前都要memset一下 初始化数组。
AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=1e5;
struct node{
int l;
int r;
int num;
}edge[MAX+5];
int vis[MAX+5];
int ans[MAX+5];
bool cmp(node a,node b)
{
if(a.r==b.r){
return a.l<b.l;
}
return a.r>b.r;
}
int sum(int x)
{
int ans=0;
for(int i=x;i>0;i-=i&(-i)){
ans+=vis[i];
}
return ans;
}
void add(int x, int a)
{
for(int i=x;i<=MAX;i+=(i&(-i))){
vis[i]+=a;
}
}
int main()
{
int n;
while(~scanf("%d",&n),n){
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++){
scanf("%d%d",&edge[i].l,&edge[i].r);
edge[i].num=i;
}
sort(edge,edge+n,cmp);
for(int i=0;i<n;i++){
if(i&&edge[i].l==edge[i-1].l&&edge[i].r==edge[i-1].r){
ans[edge[i].num]=ans[edge[i-1].num];
}
else{
ans[edge[i].num]=sum(edge[i].l+1);
}
add(edge[i].l+1,1);
}
for(int i=0;i<n;i++){
if(i==0){
printf("%d",ans[i]);
}
else{
printf(" %d",ans[i]);
}
}
printf("\n");
}
return 0;
}
三、Stars
Cows
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 23665 | Accepted: 7962 |
Description
Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.
Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John's N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].
But some cows are strong and some are weak. Given two cows: cowi and cowj, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cowi is stronger than cowj.
For each cow, how many cows are stronger than her? Farmer John needs your help!
Input
The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 105), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 105) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.
The end of the input contains a single 0.
Output
For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cowi.
Sample Input
3
1 2
0 3
3 4
0
Sample Output
1 0 0
Hint
Huge input and output,scanf and printf is recommended.
思路:
和上面的stars基本一样而且还不需要排序
排序限定了y从小到大 只需要判断x比其小的数目即可
注意:该题目范围还是从0开始 所以要注意add(x) 变为 add(x+1)
同时sum(x) 变为 sum(x+1)
AC代码:
#include<stdio.h>
typedef long long LL;
const int MAX=42000;
struct node{
LL x;
LL y;
LL num;
}edge[MAX+5];
LL vis[MAX+5];
LL ans[MAX+5],flag[MAX+5];
void add(LL x,LL a)
{
for(LL i=x;i<=MAX;i+=i&(-i)){
vis[i]+=a;
}
}
LL sum(int x)
{
LL ans=0;
for(LL i=x;i>0;i-=i&(-i)){
ans+=vis[i];
}
return ans;
}
int main()
{
LL n;
scanf("%lld",&n);
for(LL i=0;i<n;i++){
scanf("%lld%lld",&edge[i].x,&edge[i].y);
edge[i].num=i;
}
for(LL i=0;i<n;i++){
if(i&&edge[i].x==edge[i-1].x&&edge[i].y==edge[i-1].y){
ans[edge[i].num]=ans[edge[i-1].num];
}
else{
ans[edge[i].num]=sum(edge[i].x+1);
}
flag[ans[edge[i].num]]++;
add(edge[i].x+1,1);
}
for(LL i=0;i<n;i++){
printf("%lld\n",flag[i]);
}
return 0;
}
Ultra-QuickSort (求逆序数+离散化处理)、Cows、Stars【树状数组】的更多相关文章
- 【bzoj3289】Mato的文件管理 离散化+莫队算法+树状数组
原文地址:http://www.cnblogs.com/GXZlegend/p/6805224.html 题目描述 Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份 ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...
- poj 2299 树状数组求逆序数+离散化
http://poj.org/problem?id=2299 最初做离散化的时候没太确定可是写完发现对的---由于后缀数组学的时候,,这样的思维习惯了吧 1.初始化as[i]=i:对as数组依照num ...
- POJ 2182 Lost Cows 【树状数组+二分】
题目链接:http://poj.org/problem?id=2182 Lost Cows Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- 计蒜客模拟赛D2T2 蒜头君的排序:区间逆序对(移动端点) + 树状数组
题目链接:https://nanti.jisuanke.com/t/16443 题意: 给你一个由1~n构成的正整数序列,有m组询问,每组询问要求输出[l , r]区间内的逆序对个数. 数据范围: 对 ...
- POJ 2481 Cows(树状数组)
Cows Time Limit: 3000MS Memory L ...
- [POJ2182]Lost Cows(树状数组,二分)
题目链接:http://poj.org/problem?id=2182 题意:给定1~n个数和n个位置,已知ai表示第i个位置前有ai个数比当前位置的数小,求这个排列. 和刚才YY的题意蛮接近的,用树 ...
- luogu 2154 离散化+杨辉三角+树状数组
将纵向固定,每次在横向找两个点,计算其中间墓地的贡献答案,离散化后同一行的预处理个数, 树状数组内存储C[up[i]][k] * C[down[i][k] 的值,每次更新时 down[横坐标]++; ...
- POJ 2481 Cows 【树状数组】
<题目链接> 题目大意: 就是给出N个区间,问这个区间是多少个区间的真子集. 解题分析: 本题与stars类似,只要巧妙的将线段的起点和终点分别看成 二维坐标系中的x,y坐标,就会发现,其 ...
随机推荐
- 王艳 201771010127《面向对象程序设计(java)》第一周学习总结
王艳 201771010127<面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.co ...
- Java——动态创建Class(不写入文件,直接从内存中创建class)
原文:https://blog.csdn.net/zhao_xinhu/article/details/82499062#commentsedit 参考:https://www.cnblogs.com ...
- 飞机调度 Now or Later? LA 3211 (2-SAT问题)
洛谷题目传送门 题目描述 有n架飞机需要着陆.每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种.第i架飞机的早着陆时间为Ei,晚着陆时间为Li,不得在其他时间着陆.你的任务是为这些 ...
- windows下grunt的快速入门
1.认识grunt grunt是什么:他是一套前端自动化工具,是一个基于nodejs的命令行工具.(Grunt和Grunt插件是通过npm 安装并管理的,所以首先要安装nodejs). grunt ...
- 【译】Welcome to C# 9.0
C# 9.0正在形成,我想分享我们对添加到该语言下个版本的一些主要功能的看法.对于每个新版本的 C#,我们努力使常见的编码方案更加清晰和简单,C# 9.0 也不例外.这次的一个特别重点是支持数据形状的 ...
- IC-二进制, 自然数, 有符号数
https://mp.weixin.qq.com/s/9rGs9yN-OvLvEclnDZr87Q 零. 概念和结论 1. 数:概念名,指代物体的多少,即物体的量的概念: 2. 值:概念属性,数的 ...
- Window10:不能建立到远程计算机的连接,你可能需要更改此连接的网络设置。
一,右键我的电脑点击管理. 二,在系统工具中找到设备管理,在设备管理中找到网络适配器. 三,在网络适配器中找到WAN Miniport(IP) 四,找到WAN Miniport(IP)右键放心卸载,作 ...
- Java实现 LeetCode 725 分隔链表(暴力)
725. 分隔链表 给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分. 每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 nu ...
- Java实现 LeetCode 463 岛屿的周长
463. 岛屿的周长 给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域. 网格中的格子水平和垂直方向相连(对角线方向不相连).整个网格被水完全包围,但其中恰好有一个岛屿(或者 ...
- Java实现 蓝桥杯VIP 基础练习 回形取数
问题描述 回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度.一开始位于矩阵左上角,方向向下. 输入格式 输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列.接下来m ...