In the Army Now

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

/**运气真好,连做两个树状数组**/
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <numeric>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long  ll;
typedef unsigned long long ull;

int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};//up down left right
bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;}
int hashmap(int x,int y,int m){return (x-1)*m+y;}

#define eps 1e-8
#define inf 0x7fffffff
#define debug puts("BUG")
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define lowbit(x) (-x)&x
#define maxn 10010

/**题目其实就是求所给的多组数列中,哪一组数列的逆序对数最多,相同的话,输出考前的序列的序号**/
struct A
{
    int id,v;
}a[maxn];
int sum,ans,maxs=-1;//注意,数列的逆序对数可能为0,这是记录最大逆序对数的变量,就没办法和逆序对数为0的那一组比较了
                    //sum存一组序列的逆序对数,ans记录行号
int N,K;

int s[maxn+10];    //树状数组
void change(int x)//每次输入一个数字,将将其插入,插入位置记录为1,未插入数字的地方记录为0
{
    while(x<=N)
    {
        s[x]++;
        x+=lowbit(x);
    }
}

int query(int x)//查询从1~x插入了多少个数字
{
    int ans=0;
    while(x>0)
    {
        ans+=s[x];
        x-=lowbit(x);
    }
    return ans;
}

int main()
{
    scanf("%d%d",&N,&K);
    for(int i=1;i<=K;i++)
    {
        memset(a,0,sizeof(a));//每次计算都需要初始化
        memset(s,0,sizeof(s));
        sum=0;//初始化
        for(int j=1;j<=N;j++)
        {
            scanf("%d",&a[j].v);
            a[j].id=i;
            sum+=(j-1)-query(a[j].v-1);//已插入的个数 - 当前数字前面的数字插入的个数 = 当前数字的逆序对数
            change(a[j].v);   //插入当前数字
        }

        if(sum>maxs)
        {
            maxs=sum;
            ans=i;//记录行号
        }
    }

    printf("%d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值