2021.07.01膜你赛

写在前面:zx gg AK力%%% 以及 youwike gg 太强辣%%%

lj女士:今天的题就是拼手速,两个小时以内 AK。所以不需要任何交流。然而最后还是交流了

题面

A.怪物猎人

背包+一点贪心思想

推式子:

[f(k) = sum_{i=1}^{k} [a_i + (i-1) imes d] imes [b_i + (i-1) imes d] ]

[f(k) = sum_{i=1}^{k} [a_i imes b_i + (i-1) imes d imes (a_i + b_i) + (i-1)^2 imes d^2] ]

我们可以看出,第一、三项都是定值,只有第二项 ((i-1) imes d imes (a_i + b_i)) 是不定的

所以我们按 (a_i+b_i) 降序排序,使得大的数 ( imes d) 的个数尽量小,从而保证答案最小

(code)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 3010
#define maxm 300010
#define int long long
using namespace std;
template<typename T>
inline void read(T &x){
	x=0;bool flag=0;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
	if(flag) x=-x;
}

int n,m,d,h[maxm];
int g[maxn][maxn],f[maxn][maxn];
struct node{
	int a;
	int b;
}e[maxn];

bool cmp(node x,node y){
	return x.a+x.b>y.a+y.b;
}

void dp(){
	memset(f,0x3f,sizeof(f));
	for(int i=0;i<=n;i++) f[i][0]=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			g[i][j]=(e[j].a+(i-1)*d)*(e[j].b+(i-1)*d);
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			f[i][j]=min(f[i-1][j],f[i-1][j-1]+g[j][i]);//g[j][i]********
		}
	}
}

signed main(){
	read(n),read(m),read(d);
	for(int i=1;i<=n;i++) read(e[i].a);
	for(int i=1;i<=n;i++) read(e[i].b);
	for(int i=1;i<=m;i++) read(h[i]);
	sort(e+1,e+n+1,cmp);
	dp();
	for(int i=1;i<=m;i++) printf("%lld ",lower_bound(f[n]+1,f[n]+n+1,h[i])-f[n]-1);
	printf("
");
	return 0;
}
/*
3 4 5
50 10 100
60 200 25
2000 5400 9350 9400
//
0 2 2 3
*/

B.无敌的宠物

线段树板子,普通线段树 or 树状数组均可

数据很毒瘤,注意开long long

C.bamboo

看懂题就比较好做了

就是求 (1)(n) 的最小距离

判一判当前两点是否符合条件(是否能在限制距离内走到),若符合就在这两点之间连条边,跑最短路即可

D.水杯

从序列中顺序选数,选的数可加入单调队列的队头或队尾(初始队列为空),求队列最长是多少

最长上升子序列+最长下降子序列

附徐神的超短代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 400010
#define int long long
using namespace std;
template<typename T>
inline void read(T &x){
	x=0;bool flag=0;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
	if(flag) x=-x;
}

int n,a[maxn],f[maxn],g[maxn],ans;

signed main(){
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	memset(f,0x3f,sizeof(f));
	memset(g,0x3f,sizeof(g));
	for(int i=n,res;i>=1;i--){
		int f1=upper_bound(f,f+n,a[i])-f;
		int f2=lower_bound(f,f+n,a[i])-f;
		f[f1]=a[i];
		a[i]=-a[i];
		int g1=upper_bound(g,g+n,a[i])-g;
		int g2=lower_bound(g,g+n,a[i])-g;
		g[g1]=a[i];
		int tmp1=0,tmp2=0;
		if(f[f2]==-a[i]) tmp1=f1-f2;
		if(g[g2]==a[i]) tmp2=g1-g2;
		res=min(tmp1,tmp2);
		ans=max(ans,f1+g1-res+1);
	} 
	cout<<ans<<endl;
}
/*
4
1
4
2
3
//
3
*/

E.大白兔的聚会

==没有上司的舞会 考过不止一次了

树形DP 0不选1选

原文地址:https://www.cnblogs.com/DReamLion/p/14959611.html