一、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【树状数组】的更多相关文章

  1. 【bzoj3289】Mato的文件管理 离散化+莫队算法+树状数组

    原文地址:http://www.cnblogs.com/GXZlegend/p/6805224.html 题目描述 Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份 ...

  2. poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)

    题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...

  3. poj 2299 树状数组求逆序数+离散化

    http://poj.org/problem?id=2299 最初做离散化的时候没太确定可是写完发现对的---由于后缀数组学的时候,,这样的思维习惯了吧 1.初始化as[i]=i:对as数组依照num ...

  4. POJ 2182 Lost Cows 【树状数组+二分】

    题目链接:http://poj.org/problem?id=2182 Lost Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  5. 计蒜客模拟赛D2T2 蒜头君的排序:区间逆序对(移动端点) + 树状数组

    题目链接:https://nanti.jisuanke.com/t/16443 题意: 给你一个由1~n构成的正整数序列,有m组询问,每组询问要求输出[l , r]区间内的逆序对个数. 数据范围: 对 ...

  6. POJ 2481 Cows(树状数组)

                                                                      Cows Time Limit: 3000MS   Memory L ...

  7. [POJ2182]Lost Cows(树状数组,二分)

    题目链接:http://poj.org/problem?id=2182 题意:给定1~n个数和n个位置,已知ai表示第i个位置前有ai个数比当前位置的数小,求这个排列. 和刚才YY的题意蛮接近的,用树 ...

  8. luogu 2154 离散化+杨辉三角+树状数组

    将纵向固定,每次在横向找两个点,计算其中间墓地的贡献答案,离散化后同一行的预处理个数, 树状数组内存储C[up[i]][k] * C[down[i][k] 的值,每次更新时 down[横坐标]++; ...

  9. POJ 2481 Cows 【树状数组】

    <题目链接> 题目大意: 就是给出N个区间,问这个区间是多少个区间的真子集. 解题分析: 本题与stars类似,只要巧妙的将线段的起点和终点分别看成 二维坐标系中的x,y坐标,就会发现,其 ...

随机推荐

  1. php IE中文乱码

    echo mb_convert_encoding("你是我的朋友", "big5", "GB2312"); 详细出处参考:http://ww ...

  2. BZOJ 1070 拆点 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 5860  Solved: 2487[Submit][Status] ...

  3. 转 js自定义事件——Event和CustomEvent

    之前在学习自定义事件时,在MDN的Event.initEvent()页面顶端有写:该特性已从Web标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性. 作 ...

  4. MySQL复制表结构以及复制表等等

    mysql中用命令行复制表结构的方法主要有一下几种: 1.只复制表结构到新表 1 CREATE TABLE 新表 SELECT * FROM 旧表 WHERE 1=2; 或 1 CREATE TABL ...

  5. [JavaWeb基础] 024.Socket编程之简单的聊天程序

    1.Socket的简介 1)什么是Socket 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket ...

  6. PreparedStatement实现针对不同表的通用查询操作

    PreparedStatement实现针对不同表的通用查询操作:查询一样和多行 PreparedStatementQueryTest package com.aff.PreparedStatement ...

  7. for循环结构的使用

    /* for循环格式: for(①初始化条件; ②循环条件 :③迭代部分){ //④循环体 } 执行顺序:①-②-④-③---②-④-③-----直至循环条件不满足 退出当前循环 * */ publi ...

  8. Netty学习笔记(一) - 简介和组件设计

    在互联网发达的今天,网络已经深入到生活的方方面面,一个高效.性能可靠的网络通信已经成为一个重要的诉求,在Java方面需要寻求一种高性能网络编程的实践. 一.简介 当前JDK(本文使用的JDK 1.8) ...

  9. Spring boot Sample 002之spring-boot-banner

    一.环境 1.1.Idea 2020.1 1.2.JDK 1.8 二.目的 学习Spring Boot Banner自定义的操作   三.步骤 3.1.点击File -> New Project ...

  10. 结合 AOP 轻松处理事件发布处理日志

    结合 AOP 轻松处理事件发布处理日志 Intro 前段时间,实现了 EventBus 以及 EventQueue 基于 Event 的事件处理,但是没有做日志(EventLog)相关的部分,原本想增 ...