CSUSTOJ-白银御行想展示(思维题)
题目连接:http://acm.csust.edu.cn/problem/4050
CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/109455219
Description
白银御行有一个不为人知的秘密,那就是身为学生会会长,他的排球打的有亿点点差,于是热心的藤原书记主动提出要帮助他练习排球,假设排球有很多技能要学, 比如发球,拦网,救球等,假设排球有 \(n\) 个技能,虽然白银排球打的很差,但也偷偷练习过每个技能,每个技能都有一定失误率 \(a_i\) 和基础熟练度 \(b_i\) , 我们把 \(n\) 个技能标号为 \(1, 2, 3, ....,n\) , 白银会先按编号从左到右的练习某些技能, 再从右到左的把余下的技能练习一次,比如 \(1, 2, 3, 4 , 5, 6\) ,六个技能, 它可以按照先 \(1,3,4,6\) 再 \(5, 2\) 的顺序练习,或者先 \(1, 2, 3\) 再 \(6, 5, 4\) 的顺序练习, 但是不可以 \(1, 6, 4\) 再 \(5, 3, 2\) 这样的顺序练习。
假设白银第 \(j\) 个练习技能 \(i\) ,那么他会获得 \(j * b_i\) 的熟练度,并且该技能的失误率会下降 \(i\) 由于白银数学很好,他会选择一种顺序使得他最后获得的熟练度的和最大, 如果存在多种方案,他会选择一种字典序最小的方案。训练结束后他会确认 \(t\) 个技能的失误率。
请你计算出白银可以获得的熟练度和的最大值,以及他确认的每个技能的失误率。
input
第一行n(表示员工的个数),k\((1<=n,k<=1e6)\)(一定有n=k)
第二行n个整数数\(a_1,a_2,a_3....a_n\)(表示每个技能的失误率)\((-1e7<=a_i<=1e7)\)
第三行n个整数\(b_1,b_2,b_3...b_n\)(表示每个技能的基础熟练度)\((0<=b_i<=1e6)\)
第四行t,表示询问的次数\((t<=1e5)\)
接下来t行,表示询问第 \(m\) 个技能的失误率
output
一行输出白银能获得的熟练度和的最大值
对于每一组询问输出两行,
第一行一个答案,表示该技能的失误率,如果该技能的失误率为负数,那么白银会非常高兴,并在第二行输出"I Love Work!",否则请空一行。
Sample Input 1
8 8
-1 -5 5 2 7 10 100 7
1 100 2 6 0 10 13 5
3
1
5
6
Sample Output 1
996
-2
I Love Work!
3
3
Hint
对于样例,白银选择的顺序是:1 3 4 5 8 7 6 2
emmmm,可能是我语文不太好QAQ,每次出的题目都是又臭又长导致许多可写题都直接劝退了许多人。。。。遭人魔改之后题面出现了问题,真的很抱歉,题面的k被人删了。。。
我们可以先假设所有的人都是第一波选择,那么我们从前往后决定这个人是否是应该在第二波选。对于第一个人,它要么第1个选,要么第n个选,当它从第一个移动到第n个的时候,它有的贡献就是\((n-1)*b_i\),但它会将后面的数全部往前移动一个单位,所以他还有一个贡献为\(-\sum_{i=2}^{n}b_i\),如果这两个数的和的贡献为正数,那么也就是说他移动到后面是更优的,那么我们就直接决定选他在后面一波走人,那么接下来的第二个人和第三个人也就出来了
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mac=1e6+10;
ll sum[mac];
int a[mac],id[mac],b[mac];
int main(int argc, char const *argv[])
{
int n,k;
scanf ("%d%d",&n,&k);
for (int i=1; i<=n; i++)
scanf ("%d",&a[i]);
for (int i=1; i<=n; i++)
scanf ("%d",&b[i]),sum[i]=b[i]+sum[i-1];
ll l=1,r=n;
ll ans=0;
for (int i=1; i<=n; i++){
ll cong=(r-l)*b[i]-(sum[n]-sum[i]);
if (cong>0){
id[r]=i; ans+=1LL*b[i]*r;
r--;
}
else {
id[l]=i; ans+=1LL*b[i]*l;
l++;
}
}
printf ("%lld\n",ans);
for (int i=1; i<=n; i++)
a[id[i]]-=i;
int t;
scanf ("%d",&t);
while (t--){
int m;
scanf ("%d",&m);
printf ("%d\n",a[m]);
if (a[m]<0) printf("I Love Work!");
printf("\n");
}
return 0;
}