亵渎
按生物血量升序排序,然后对于相邻的两个怪的血量差 ,有两种可能:
或 ,这样的会因为前面一个怪死掉而死掉
,这样会在前面一个怪死掉以后,还需使用 个亵渎这个怪才能死
于是 思路就出来了
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int a[100001],n,ans;
int main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
ans+=a[1];
for (int i=2;i<=n;i++)
{
if (a[i]>(a[i-1]+1))ans+=a[i]-a[i-1]-1;
}
cout<<ans;
}
n年前写的都没写快读,大括号还要换行
无畏天马
插一句,淘宝有卖这本书的,但是没看过 的不知道能不能看懂(雾)
存图挺难的,按dfs序跑,一个全局变量 记录出边指向的点,然后对于一个箱子解锁的时间,就相当于我们再走一条走廊,开箱子不需要时间
中间的点的 都设为 (迎合读入),有箱子的点 设为古画的数量
之后就是裸的树形 分组背包了,记 表示 到 这条边的边权,那么 式就是
细节方面,我们既然要出去,那一定每一条路径都要经历“往里走”和“往外走”两个过程,也就是一定会走两次,存图的时候边权自动双倍就好了
还有个问题,就是如果你恰好用了 秒,你出门是会和水猿碰面的,所以时间在读入的时候就要
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define reg register
using namespace std;
const int orz=500100;
struct EDGE{
int ver,dis,nxt,pre,num;
}edge[orz];
int head[orz],n,m,cnt,dfs_cnt,size[orz],v=2;
int dis[orz],s,l,r,f[5001][1001],ans,tim[orz];
inline int read(){
int sym=0,res=0;char ch=0;
while (ch<'0'||ch>'9')sym|=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9')res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return sym?-res:res;
}
inline void add(int u,int v,int t){
edge[++cnt].ver=v;
edge[cnt].nxt=head[u];
edge[cnt].dis=t;
head[u]=cnt;
}
inline void dfs(int u){
int t=read()<<1,tmp=read();v++;add(u,v,t);
if (tmp){
add(v,v+1,tim[++dfs_cnt]);dis[++v]=tmp;
}else{
dfs(v);
}
t=read()<<1;tmp=read();v++;add(u,v,t);
if (tmp){
add(v,v+1,tim[++dfs_cnt]);dis[++v]=tmp;
}else{
dfs(v);
}
}
inline void dp(int u){
f[u][0]=dis[u];
for (reg int i=head[u];i;i=edge[i].nxt){
int v=edge[i].ver;dp(v);
for (reg int j=s;j>=edge[i].dis;--j){
for (reg int k=j-edge[i].dis;k>=0;--k){
f[u][j]=max(f[u][j],f[v][k]+f[u][j-k-edge[i].dis]);
}
}
}
}
int main(){
n=read();s=read()-1;
for (reg int i=1;i<=n;i++){
tim[i]=read();
}
int t=read()<<1,tmp=read();add(1,2,t);
if (!tmp)dfs(2);
else add(2,3,tim[1]),dis[3]=tmp;
dp(1);
for (reg int i=1;i<=s;i++){
ans=max(ans,f[1][i]);
}
printf("%d",f[1][s]);
return 0;
}
全是卡常好丑啊