LuoguP5016 [NOIP2018 普及组] 龙虎斗 题解

听说CSP前发题解会\(RP++\)

纪念我\(CSP2019\)前最后一篇题解。

这题是\(NOIP2018\)普及组的第二题,我当时才刚学\(OI\)不到八个月,写出了个这样奇葩的代码:

#include <cstdio>
#include <cmath>
using namespace std;

int main() {
    int n,c[100002],m,p1,s1,s2,p2;
    float a[100002];
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
        scanf("%d",&c[i]);
    scanf("%d%d%d%d",&m,&p1,&s1,&s2);
    int l=0,h=0;
    for(int i=1; i<m; ++i)
        l+=c[i]*(m-i);
    for(int i=m+1; i<=n; ++i)
        h+=c[i]*(i-m);
    if(s1<m)    l+=s1*(m-p1);
    else if(s1>m)   h+=s1*(p1-m);
    if(l<h) {
        for(int i=1; i<m; ++i)
            a[i]=abs((m-i)-m/(float)s2);
        p2=1;
        for(int i=2; i<m; ++i)
            if(a[i]<a[p2])
                p2=i;
    } else {
        for(int i=m+1; i<=n; ++i)
            a[i]=abs((i-m)-m/(float)s2);
        p2=m+1;
        for(int i=m+2; i<=n; ++i)
            if(a[i]<a[p2])
                p2=i;
    }
    printf("%d",p2);
    return 0;
}

(不要吐槽我以前的码风qwq)

结果只有\(36\)分。

今天我一看的时候我就疯了:我那时真傻,这题哪要用除法,直接暴力模拟轻松搞定啊:)

于是我决定今天无论如何都要做这道题目。

结果,一开始\(4\)分,这让我很是尴尬,改了一些细节的错误之后,终于到了——\(64\)分。

我这才发现两个问题:

\(1)\) 要是这个天降空兵空降到了分界兵营里面呢?

\(2)\) 要是无论如何都不能将差值缩小呢?

其实这两个问题都好解决,并且都是一个问题,都可以归化到\(2)\)这个问题上去。

我们先枚举完加入某个兵营的最小差值,然后判断这是否比原来的差值还要大,如果是这样就要将他们放入分界兵营里面,谁也不干涉谁,否则按照原样处理即可。

不多说了,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define ll long long

ll n, s1, s2, p1, c[100007], ans, m, d, t, p2 = 9223372036854775807;	//牢记去年不开long long见祖宗的教训 

inline ll read() {
	ll f = 1, x = 0;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-')	f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}

int main() {
	n = read();
	for(ll i = 1; i <= n; ++i)
		c[i] = read();
	m = read(), p1 = read(), s1 = read(), s2 = read();
	for(int i = 1; i < m; ++i) {
		d += c[i] * (m - i);
		if(i == p1)	d += s1 *(m - i);
	}
	for(int i = m + 1; i <= n; ++i) {
		t += c[i] * (i - m);
		if(i == p1)	t += s1 * (i - m);
	}
//	printf("%lld %lld\n", d, t);
	if(d < t) {
		for(int i = 1; i < m; ++i) {
			if(abs((m - i) * s2 + d - t) < p2) {
				p2 = abs((m - i) * s2 + d - t);
				ans = i;
			}
		}
	} else {
		for(int i = m + 1; i <= n; ++i)
			if(abs((i - m) * s2 + t - d) < p2) {
				p2 = abs((i - m) * s2 + t - d);
				ans = i;
			}
	}
	if(p2 > abs(d - t)) {
		printf("%lld", m);
		return 0;
	}
	printf("%lld", ans);
	return 0;
}

祝大家CSP2019_J/S RP++!

posted @ 2021-12-23 20:59  Eason_AC  阅读(74)  评论(0)    收藏  举报