题目:考分鄙视

题目描述

    Whence这个学期考了 n次试,每一次都有一个0~20000之间的整数分数。Whence本来的状态应该是每一次考试都比前一次多一分(除第一次),但由于他很不稳定,偏差可能很大。对于第i次考试,如果有第j次考试满足1≤j ≤ i ≤n,且以第j次考试分数作为基准估计的第i次考试成绩比实际成绩低,就说第i次考试鄙视了第j次考试(估计分可以超过20000)。为了提高自信,Whence想知道他这个学期所有考试总共有多少次鄙视。

输入输出格式

输入格式:

第 1 行 n (1 第2行为n次考试成绩。

输出格式:

1行,这个学期所有考试的总共鄙视次数(总数可能很大,只需要输出总数mod 12345的值)。

输入输出样例

输入样例#1:

4
1 3 3 5

输出样例#1:

3

提示信息提示

样例说明:第一次考试的分数是1,那么估计应该是第二次为2,第三次为3,第四次为4,但第二次实际分数为3,比2大,这是1次鄙视;第四次实际分数为5,比估计的4大,这也是1次鄙视;第二次考试的分数是3,那么估计应该是第三次为4,第四次为5,实际分数分别是3和5,所以没有鄙视;第三次考试的分数为3,那么估计第四次是4,但实际为5,这又是1次鄙视。因此总鄙视次数为3次。

算法

1.暴力

根据题意枚举每一次的预估分数并与实际分数比较:

#include<bits/stdc++.h>
using namespace std;
int n;
int a[50001],ans=0,b[50001];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			b[j]=a[i]+(j-i);
			if(b[j]<a[j]) ans=(ans+1)%12345;
		}
	}cout<<ans;
	return 0;
}

时间复杂度(O(n^2))

空间复杂度(O(n))

TLE

算法2

归并排序实现逆序对+数学变形:

将 b[j]=a[i]+(j-i) 代入 b[j]<a[j]

a[i]+j-i<a[j]

变形得a[i]-i<a[j]-j

将所有a[i]提前减去i

则“a[i]<a[j]”

for(int i=1;i<=n;i++)
{
	cin>>a[i];
	a[i]-=i;
}
for(int i=1;i<=n;i++)
{
	for(int j=i+1;j<=n;j++)
	{
		if(a[i]<a[j])ans=(ans+1)%12345;
	}
	cout<<endl;
}

转化为求逆序对:

#include<bits/stdc++.h>
using namespace std;
int n;
int a[500001],ans=0,b[500001];
void f(long long l, long long r)
{
	if(l==r) return;
	long long mid=(l+r)/2;
	f(l,mid);
	f(mid+1,r);
	long long i=l,k=l,j=mid+1;
	while(i<=mid&&j<=r)
	{
		if(a[i]>a[j]) 
		{
			ans+=(mid-i)+1;
			ans%=12345;
			b[k++]=a[j++];
		}
		else b[k++]=a[i++];
	}
	while(i<=mid) b[k++]=a[i++];
	while(j<=r) b[k++]=a[j++];
	for( long long i=l;i<=r;i++) a[i]=b[i];
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		a[i]-=i;
	}
	reverse(a+1,a+n+1);
	f(1,n);
	cout<<ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值