1090. In the Army Now (Ural 1090 归并排序||树状数组)

1090. In the Army Now

Time limit: 1.0 second

Memory limit: 64 MB

The sergeant ordered that all the recruits stand in rows. The recruits have formed K rows with Npeople in each, but failed to stand according to their height. The right way to stand
in a row is as following: the first soldier must be the highest, the second must be the second highest and so on; the last soldier in a row must be the shortest. In order to teach the young people how to form rows, the sergeant ordered that each of the recruits
jump as many times as there are recruits before him in his row who are shorter than he. Note that there are no two recruits of the same height.

The sergeant wants to find which of the rows will jump the greatest total number of times in order to send this row to work in the kitchen. Help the sergeant to find this row.

Input

The first line of the input contains two positive integers N and K (2 ≤ N ≤ 10000, 1 ≤ K ≤ 20). The following K lines contain N integers each. The
recruits in each row are numbered according to their height (1 — the highest, N — the shortest). Each line shows the order in which the recruits stand in the corresponding row. The first integer in a line is the number of the first recruit in a row
and so on. Therefore a recruit jumps as many times as there are numbers which are greater than his number in the line before this number.

Output

You should output the number of the row in which the total amount of jumps is the greatest. If there are several rows with the maximal total amount of jumps you should output the minimal of their numbers.

Sample

input output
3 3
1 2 3
2 1 3
3 2 1
3

题意:k行n列,求出每一列的逆序对,输出逆序对最少的所在的行数。

思路:采用归并排序或者树状数组,这两天写了好几道了,要练熟悉!

代码:

//归并排序
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 10005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

int n,k,sum;
int a[maxn];
int b[maxn];

void Merge(int a[],int l,int mid,int r)
{
    int i,j,k=l;
    FRE(i,l,r) b[i]=a[i];
    i=l;j=mid+1;
    while (i<=mid&&j<=r)
    {
        if (b[i]<=b[j])
            a[k++]=b[i++];
        else{
            sum+=(mid-i+1);
            a[k++]=b[j++];
        }
    }
    while (i<=mid) a[k++]=b[i++];
    while (j<=r) a[k++]=b[j++];
}

void Merge_sort(int a[],int l,int r)
{
    if (l>=r) return ;
    int mid=(l+r)>>1;
    Merge_sort(a,l,mid);
    Merge_sort(a,mid+1,r);
    Merge(a,l,mid,r);
}

int main()
{
    int i,j;
    while (~sff(n,k))
    {
        int maxx=0;
        int ans=1;
        FRE(i,1,k)
        {
            sum=0;
            FRE(j,1,n)
                sf(a[j]);
            Merge_sort(a,1,n);
            if (sum>maxx)
            {
                maxx=sum;
                ans=i;
            }
        }
        pf("%d\n",ans);
    }
    return 0;
}
//树状数组
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 10005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

struct Node
{
    int val,pos;
}node[maxn];

int n,k,ans,s;
int bit[maxn];

int cmp(Node a,Node b)
{
    return a.val>b.val;
}

int sum(int i)
{
    int s=0;
    while (i>0)
    {
        s+=bit[i];
        i-=i&-i;
    }
    return s;
}

void add(int i,int x)
{
    while (i<=n)
    {
        bit[i]+=x;
        i+=i&-i;
    }
}

int main()
{
    int i,j;
    while (~sff(n,k))
    {
        ans=1;
        int maxx=-1;
        FRE(i,1,k)
        {
            s=0;
            mem(bit,0); //一定要记住初始化
            FRE(j,1,n)
            {
                sf(node[j].val);
                node[j].pos=j;
            }
            sort(node+1,node+n+1,cmp);
//            DBG;
            FRE(j,1,n)
            {
//                DBG;
                s+=sum(node[j].pos-1);
                add(node[j].pos,1);
            }
            if (s>maxx)
            {
                maxx=s;
                ans=i;
            }
//            DBG;
        }
        pf("%d\n",ans);
    }
    return 0;
}
时间: 2024-08-27 04:01:28

1090. In the Army Now (Ural 1090 归并排序||树状数组)的相关文章

UVA 11990 `Dynamic&#39;&#39; Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2

题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3141 题意 一个1到n的排列,每次随机删除一个,问删除前的逆序数 思路 综合考虑,对每个数点,令value为值,pos为位置,time为出现时间(总时间-消失时间),明显是统计value1 > value2, pos1 < pos2, time1 < time2的个

nyist oj 117 求逆序数 (归并排序&amp;&amp;树状数组)

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组数(1<=T<=5) 每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000) 随后的一行共有N个整

Ultra-QuickSort (poj 2299 归并排序 || 树状数组 求逆序对)

Language: Default Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 45751   Accepted: 16615 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct i

代码与算法集锦-归并排序+树状数组+快排+深度优先搜索+01背包(动态规划)

归并排序 求逆序数 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 首先考虑下如何将将二个有序数列合并.这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数.然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可. //将有序数组a[]和b[]合并到c[]中 void MemeryArray(int a[], int n, int b[], int m, int c

【XSY2669】归并排序 树状数组 简单组合数学

题目描述 有一个长度为\(n\)的排列\(n=2^k\),你要把这个数组归并排序.但是在长度为\(2\)的时候有\(\frac{1}{2}\)的概率会把两个数交换(就是有\(\frac{1}{2}\)的概率返回错的结果).有两种操作 \(1\):交换两个数 \(2\):询问排序后的一个位置等于一个数的概率. \(k\leq 16,q\leq {10}^5\) 题解 这个排序有点奇怪.两个数\(a,b(a<b)\)排序后可能是\(ab\)也可能是\(ba\). 观察到\(ab\)会正常排序,而\(

洛谷 P1908 逆序对 Label:归并排序||树状数组

题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对.知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目. 输入输出格式 输入格式: 第一行,一个数n,表示序列中有n个数. 第二行n个数,表示给定的序列. 输出格式: 给定序列中逆序对的数目. 输入输出样例 输

POJ 2299 Ultra-QuickSort (树状数组or 归并排序分治求逆序对数)

题目大意就是说帮你给一些(n个)乱序的数,让你求冒泡排序需要交换数的次数(n<=500000) 显然不能直接模拟冒泡排序,其实交换的次数就是序列的逆序对数. 由于数据范围是 0 ≤ a[i] ≤ 999,999,999所以先要离散化,然后用合适的数据结果求出逆序 可以用线段树一步一步添加a[i],每添加前查询前面添加比它的大的有多少个就可以了. 也可用树状数组,由于树状数组求的是(1...x)的数量和所以每次添加前查询i-sum(a[i])即可 树状数组: //5620K 688MS #incl

POJ 2299 求逆序对(归并排序或树状数组)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 45290   Accepted: 16440 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

URAL 1707. Hypnotoad&#39;s Secret(树状数组)

URAL 1707. Hypnotoad's Secret 题目链接 题意:这题设置的恶心不能多说,构造点和矩形,大概就是问每个矩形里面是否包含点 思路:树状数组,把点排序,按y轴,在按x轴,在按询问,这样每次遇到一个点就在相应的扫描线上加,遇到查询就询问出左边到这个点位置的,就能预处理出每个点左下角包含的点的个数,然后每个矩形再利用容斥原理去搞一下即可 代码: #include <cstdio> #include <cstring> #include <algorithm&