写在前面: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选