hdu 2689 Sort it

点击打开链接hdu2689

思路:线段树+单点更新
分析:
1 题目给定n个数要求最少的交换次数使得序列有序
2 显然两个数要交换肯定是满足i < j && num[i] > num[j]。那么假设现在读入一个数num[i],我们要求这个数num[i]要和前面的交换几次使得序列有序,就是查找num[0]~num[i-1]之间比num[i]大的数的个数,那么这个过程我们就可以利用线段树的查找,我们只要去查找[num[i]+1 , n]这个区间已经插入的个数即可,然后更新线段树
3 注意当num[i] == n的时候不用查找,直接更新

4 题目给定n 最大为1000,那么最话的情况下次数是1+2+3+...n,那么不会超过int。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

#define MAXN 1010

int n;
struct Node{
   int left;
   int right;
   int num;
};
Node node[4*MAXN];

//建立一颗空的线段树
void buildTree(int left , int right , int pos){
   node[pos].left = left;
   node[pos].right = right;
   node[pos].num = 0;
   if(left == right)
     return;
   int mid = (left+right)>>1;
   buildTree(left , mid , pos<<1);
   buildTree(mid+1 , right , (pos<<1)+1);
   node[pos].num = node[pos<<1].num + node[(pos<<1)+1].num;
}

//询问
int query(int left , int right , int pos){
   if(node[pos].left == left && node[pos].right == right)
      return node[pos].num;
   int mid = (node[pos].left + node[pos].right)>>1;
   if(right <= mid)
      return query(left , right , pos<<1);
   else if(left > mid)
      return query(left , right , (pos<<1)+1);
   else
      return query(left , mid , pos<<1)+query(mid+1 , right , (pos<<1)+1);
}

//更新
void update(int index , int pos){
   if(node[pos].left == node[pos].right){
      node[pos].num++;
      return;
   }
   int mid = (node[pos].left + node[pos].right)>>1;
   if(index <= mid)
     update(index , pos<<1);
   else
     update(index , (pos<<1)+1);
   node[pos].num = node[pos<<1].num+node[(pos<<1)+1].num;
}

int main(){
   int x , ans;
   while(scanf("%d" , &n) != EOF){
      buildTree(1 , n , 1);
      ans = 0;
      for(int i = 1 ; i <= n ; i++){
         scanf("%d" , &x);
         if(x != n)
           ans += query(x+1 , n , 1);
         update(x , 1);
      }
      printf("%d\n" , ans);
   }
   return 0;
}

思路:树状数组
分析:
1 题目给定n个数要求最少的交换次数使得序列有序序列
2 显然两个数要交换肯定是满足i < j && num[i] > num[j]。那么假设现在读入一个数num[i],我们要求这个数num[i]要和前面的交换几次使得序列有序,就是查找num[0]~num[i-1]之间比num[i]大的数的个数。那么如果我们用树状数组来做的话,读入num[i]的时候我们应该查找前i-1个数比num[i]大的数,那么个数就是i-1-getSum(x-1),当x为1的时候就是i-1。最后更新树状数组。(这里原数组A[I]表示的是i是否插入,A[i]的值只有0/1两种!)

3 题目给定n 最大为1000,那么最话的情况下次数是1+2+3+...n,那么不会超过int。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 1010

int num[MAXN];
int C[MAXN];

int lowbit(int x){
   return x&(-x);
}

int getSum(int x){
   int sum = 0;
   while(x > 0){
      sum += C[x];
      x -= lowbit(x);
   }
   return sum;
}

void update(int x){
   while(x <= MAXN){
      C[x] += 1;
      x += lowbit(x);
   }
}

int main(){
   int x , ans , n;
   while(scanf("%d" , &n) != EOF){
      memset(num , 0 , sizeof(num));
      memset(C , 0 , sizeof(C));
      ans = 0;
      for(int i = 1 ; i <= n ; i++){
         scanf("%d" , &x);
         if(x > 1)
           ans += i-1-getSum(x-1);
         else
           ans += i-1;
         update(x);//更新树状数组
      }
      printf("%d\n" , ans);
   }
   return 0;
}
时间: 2024-12-30 09:59:16

hdu 2689 Sort it的相关文章

HDOJ(HDU) 2523 SORT AGAIN(推导排序、、)

Problem Description 给你N个整数,x1,x2-xn,任取两个整数组合得到|xi-xj|,(0 < i,j<=N,i!=j). 现在请你计算第K大的组合数是哪个(一个组合数为第K大是指有K-1个不同的组合数小于它). Input 输入数据首先包含一个正整数C,表示包含C组测试用例. 每组测试数据的第一行包含两个整数N,K.(1< N<=1000,0< K<=2000) 接下去一行包含N个整数,代表x1,x2..xn.(0<=xi<=2000

HDOJ(HDU) 2109 Fighting for HDU(简单排序比较)

Problem Description 在上一回,我们让你猜测海东集团用地的形状,你猜对了吗?不管结果如何,都没关系,下面我继续向大家讲解海东集团的发展情况: 在最初的两年里,HDU发展非常迅速,综合各种ACM算法生成的老鼠药效果奇好,据说该药专对老鼠有效,如果被人误食了,没有任何副作用,甚至有传闻说还有健胃的效果,不过这倒没有得到临床验证.所以,公司的销量逐年递增,利润也是节节攀升,作为股东之一的公主负责财务,最近半年,她实在辛苦,多次因为点钞票造成双手抽筋而住院,现在在她面前你根本不要提到"

HDOJ(HDU) 2093 考试排名(Arrays.sort排序、类的应用)

Problem Description C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点.它的功能是怎么实现的呢? 我们做好了题目的解答,提交之后,要么"AC",要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题"AC"后,就要与你算一算帐了,总共该题错误提交了几回.虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间.特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分.这样一来,你在做出的

hdu 4430 Yukari&#039;s Birthday

点击打开链接hdu 4430 思路:枚举r+二分k 分析: 1 题目要求的是找到一组最小的r*k,如果r*k相同那么就找r最小的. 2 很明显k>=2,根据n <= 10^12,那么可以知道r的最大值r<50,所以只要枚举枚举r的值,然后二分k的大小找到所有的解,存入一个结构体里面,然后在对结构体排序,那么这样就可以得到最后的ans 3 注意题目说了中心点最多一个蜡烛,所以写二分的时候应该注意判断的条件: 4 还有可能计算得到结果超了long long直接变成负数所以应该对或则个进行判断

hdu 2109 (Fighting for HDU)

http://acm.hdu.edu.cn/showproblem.php?pid=2109 水题 #include <iostream> #include <algorithm> #include <cstdio> using namespace std; int data1[105]; int data2[105]; int main() { int m; while(cin>>m,m) { int sum1=0,sum2=0; for(int i=0;

HDU 1839 Delay Constrained Maximum Capacity Path(二分+最短路)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=1839 题目: Delay Constrained Maximum Capacity Path Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 226    Accepted Submission(s): 98 Problem Descri

HDU 2363 Cycling:二分+枚举+限制最短路,好题

链接: http://acm.hdu.edu.cn/showproblem.php?pid=2363 题目大意: 小明从家里走到学校去考试, 路上有各个交叉点,它们有自己的海拔高度. 小明从家里走到学校的路上,必然会经过不同的交叉点,因此会不断的走上走下,忐忐忑忑,这让他很不安,会影响他考试的发挥.因此,他要选择一条起伏最小的路去学校.所谓的"起伏最小",是指这条路上海拔最高的点与海拔最低的点的差值最小. 在起伏最小的前提下,还要求出路程距离最短. 分析与总结: 这题让我想起以前做过的

HDU 1598 find the most comfortable road (枚举+Kruskal)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=1598 题目: Problem Description XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的"舒适度"有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,fl

HDU 3938 Portal(离线+Kruskal+并查集)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3938 题目: Problem Description ZLGG found a magic theory that the bigger banana the bigger banana peel .This important theory can help him make a portal in our universal. Unfortunately, making a pair of por