URAL 1090. In the Army Now

URAL 1090. In the Army Now_第1张图片

题意:求逆序数对。输出逆序数对最大的一行的标号,若有多行,输出其中行数最小的一行的标号。

方法一:划分区间,由于每个数的范围都是1-N。肯定小于10000.

将10000分成100个区间,记录1-10000每个值有几个,再记录每个区间内有几个。

对于每个值,只要知道它之前的数中有多少个比它大就行了

每次搜索最多100个区间+100个值 =200次.

方法二:归并排序顺便求逆序数对。


方法一代码:


int ALL,ANS,tempA; 
int h[10101];
int Ih[102];
int N,K;
int main(void)
{
	while(cin>>N>>K){
		
		ALL=-1;ANS=1;
		for(int i=0;i<K;i++){
			memset(h,0,sizeof(h));memset(Ih,0,sizeof(Ih));
			tempA=0;
			for(int j=0;j<N;j++){
				int temp;
				scanf("%d",&temp);
				for(int i=temp;i<temp/100*100+100;i++) tempA+=h[i];
				for(int i=temp/100+1;i<=101;i++) tempA+=Ih[i];
				h[temp]++;Ih[temp/100]++;
			}
			if(~ALL) {
				if(tempA>ALL) ALL=tempA,ANS=i+1;
			}
			else ALL=tempA,ANS=i+1;
		}
		cout<<ANS<<endl;
	}
return 0;
}

方法二代码:


int R[20][10000];
int N,K;
int rank[10000];
int merge(int a[],int lo,int hi){
	if(lo>=hi) return 0;
	int mid=lo+(hi-lo)/2,ANS=0;
	ANS+=merge(a,lo,mid);
	ANS+=merge(a,mid+1,hi);
	int *b=new int[mid-lo+1];
	int *c=new int[hi-mid];
	for(int i=0;i<mid-lo+1;i++) b[i]=a[lo+i];
	for(int i=0;i<hi-mid;i++) c[i]=a[i+mid+1];
	int Ib=0,Ic=0,Ia=0;
	while(Ia<hi-lo+1){
		if(Ib <mid-lo+1&&Ic < hi-mid){
			if(b[Ib]>c[Ic]) a[lo+Ia++]=c[Ic++],ANS+=mid-lo+1-Ib;
			else a[lo+Ia++]=b[Ib++];
		}
		else if(Ib <mid-lo+1){
			a[lo+Ia++]=b[Ib++];
		}
		else if(Ic<hi-mid){
			a[lo+Ia++]=c[Ic++];
		}
	}
	delete []b;
	delete []c;
	return ANS;
} 
int main(void)
{
	while(cin>>N>>K){
		for(int i=0;i<K;i++){
			for(int j=0;j<N;j++){
				scanf("%d",&R[i][j]);
			}
		}
		int ANS=merge(R[0],0,N-1);int ANSI=0;
		for(int i=0;i<K;i++){
			int D=merge(R[i],0,N-1);
			if(D >ANS) ANS=D,ANSI=i;
		}
		cout<<ANSI+1<<endl;
	}
return 0;
}



你可能感兴趣的:(ural)