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;
}
posted @ 2020-11-07 18:33  lonely_wind  阅读(130)  评论(0编辑  收藏  举报