SOI round0 题解

比赛链接

亵渎

按生物血量升序排序,然后对于相邻的两个怪的血量差 c c ,有两种可能:

c = 0 c=0 1 1 ,这样的会因为前面一个怪死掉而死掉

c > 1 c>1 ,这样会在前面一个怪死掉以后,还需使用 c 1 c-1 个亵渎这个怪才能死

于是 O ( n log n ) O(n\log n) 思路就出来了

#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年前写的都没写快读,大括号还要换行

无畏天马

插一句,淘宝有卖这本书的,但是没看过 M L P MLP 的不知道能不能看懂(雾)

存图挺难的,按dfs序跑,一个全局变量 v v 记录出边指向的点,然后对于一个箱子解锁的时间,就相当于我们再走一条走廊,开箱子不需要时间

中间的点的 d i s dis 都设为 0 0 (迎合读入),有箱子的点 d i s dis 设为古画的数量

之后就是裸的树形 d p dp 分组背包了,记 ( u , v ) (u,v) 表示 u u v v 这条边的边权,那么 d p dp 式就是

f [ u ] [ j ] = m a x ( f [ v ] [ k ] + f [ v ] [ j ( u , v ) k ] ) , f [ u ] [ 0 ] = d i s [ u ] f[u][j]=max(f[v][k]+f[v][j-(u,v)-k]),f[u][0]=dis[u]

细节方面,我们既然要出去,那一定每一条路径都要经历“往里走”和“往外走”两个过程,也就是一定会走两次,存图的时候边权自动双倍就好了

还有个问题,就是如果你恰好用了 s s 秒,你出门是会和水猿碰面的,所以时间在读入的时候就要 1 -1

#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;
}

全是卡常好丑啊

发布了12 篇原创文章 · 获赞 0 · 访问量 109

猜你喜欢

转载自blog.csdn.net/qq_37734034/article/details/104095912
今日推荐