C. Pursuit
题意:
给t组样例
每组样例给n个数
a[1] , a[2] , a[3] ...... a[n]
b[1] , b[2] , b[3] ...... b[n]
数据保证(0 <= a[i] , b[i] <= 100 , t组样例n的总和小于1e5)
a[i]表示第一个人在i这个阶段的分数
b[i]表示第二个人在i这个阶段的分数
现在只给了n个阶段每个人的分数
后面若干个阶段的分数值0到100之间都有可能
现在定义一个人在i这个阶段的得分为
从i个分数中取出 i - i / 4 个最大的分数相加即为
在i阶段的分数
问在n这个阶段是否第一个人的得分大于第二个人的得分
如果可以输出0
如果不行输出最少加几个阶段
使得第一个人的得分大于等于第二个人的得分
思路:
既然要让a的分数要大于等于b的分数
那么a[n+1] , a[n+2] , a[n+3] ......都应该是100
b[n+1] , b[n+2] , b[n+3] ....... 都应该是0
所以从大到小排序之后
用前缀和优化到on
on枚举o1判断即可
时间复杂度:O n
#include<bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define re register int
#define pll pair<int,int>
#define x first
#define y second
#define sf(x) scanf("%d",&x)
#define sfl(x) scanf("%lld",&x)
typedef long long ll ;
using namespace std;
const int N = 1e6 + 10 , M = 2010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
int t ;
int n ;
int a[N] , b[N] ;
int s[N] , h[N] ;
int main()
{
cin >> t ;
while(t--)
{
cin >> n ;
fer(i,1,n)
{
sf(a[i]) ;
}
fer(i,1,n)
{
sf(b[i]) ;
}
sort(a + 1 , a + 1 + n) ;
sort(b + 1 , b + 1 + n) ;
reverse(a + 1 , a + 1 + n) ;
reverse(b + 1 , b + 1 + n) ;
fer(i,1,n)
{
s[i] = s[i-1] + a[i] ;
}
fer(i,1,n)
{
h[i] = h[i-1] + b[i] ;
}
fer(i,n+1,3e5)
{
s[i] = s[i-1] + 100 ;
}
fer(i,n+1,3e5)
{
h[i] = h[i-1] ;
}
if(s[n-n/4] >= h[n-n/4])
{
puts("0") ;
}
else
{
for(int i = n + 1 ; i <= N ; i ++)
{
int j = i - i / 4 ;
// j为取多少个最大的个数
int z = i - n ;
// z为有多少个多余的100可以取
int s1 , s2 ;
if(z <= j) s1 = 100 * z + s[j-z] ;
else s1 = 100 * j ;
s2 = h[j] ;
if(s1 >= s2)
{
cout << i - n << "\n" ;
break ;
}
}
}
}
return 0;
}