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坐标,就会发现,其 ...
随机推荐
- 转义URL 含有中文和特殊符号
方法1: //这个方法被废弃了 NSString *urlString = @"https://www.cnblogs.com/huaida/#/程序员"; NSString* e ...
- python基本数据类型:字符串及其方法(一)
大小写转换类 方法一:capitalize()首字母大写字符串 name='hatusne miku' name1=name.capitalize() print(name,name1) 方法二:ti ...
- C#用Linq对列表/集合进查询
namespace ---> System.Linq; 使用&&进行多条件查询 也可以直接使用Lambda表达式+扩展方法的写法:
- 项目readme文件目录生成工具 treer
生成目录的工具呢有tree和treer,但是tree不知道怎么忽略node_modules文件夹, 而treer就简单了,下面就是基本的命令了 其中-i是指忽略xxx, -e是指导出 安装 npm i ...
- spring cloud系列教程第六篇-Eureka集群版
spring cloud系列教程第六篇-Eureka集群版 本文主要内容: 本文来源:本文由凯哥Java(kaigejava)发布在博客园博客的.转载请注明 1:Eureka执行步骤理解 2:集群原理 ...
- MOS管的栅极和源极之间的电阻
MOS管的栅极和源极之间的电阻: 一是为场效应管提供偏置电压:二是起到泻放电阻的作用:保护栅极G-源极S: 保护栅极G-源极S: 场效应管的G-S极间的电阻值是很大的,这样只要有少量的静电就能使他的G ...
- [JavaWeb基础] 009.Struts2 上传文件
在web开发中,我们经常遇到要把文件上传下载的功能,这篇文章旨在指导大家完成文件上传功能 1.首先我们需要一个上传文件的页面. <!--在进行文件上传时,表单提交方式一定要是post的方式, 因 ...
- python中的数据存储认识
声明:本人是一个初学者,博客内容基本也是一些基础的东西,如果说的有什么问题欢迎纠正. 前言 许多人初学python之前应该也学习过其他的语言,比如博大精深的c语言,笔者在学习python之前就学习过c ...
- docker出现相同的image条目的删除办法
一.问题:在测试docker安装的prometheus系统时,由于异常操作,使用docker image ls出现了两条一模一样的条目,如下: [root@ELK prometheus]# docke ...
- tomcat session漏洞反序列化详解
1. 条件1)攻击者可以控制服务器上的文件名/文件内容2)tomcat context配置了persistencemanager的fileSotre3) persistenceManager 配置了s ...