1090. In the Army Now
Time limit: 1.0 second
Memory limit: 64 MB
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;
}