20181027

news/2024/11/6 4:58:16

今天我又双叒叕打炸了,膜拜一下rk1 jarden巨佬滴博客
T1:【from new_dtoj 2503: HZ(666666) loves meat(meat)】
题目描述
HZ(666666)终于打开了密码箱,发现里面只是一堆风干的肉条,于是他打算喂狗。
HZ(666666)养了n条狗,有m根肉条,他想把肉条一根不留地分给狗,并使得每条狗至少有一条肉条可吃。狗总是很贪心,它们不希望看到有其他的狗有更多的肉条,否则就会不开心。一条狗的不开心程度可以表示为他的贪心程度和拥有比它更多肉条的狗的数量的乘积。现在HZ(666666)想知道一种分配方式使得狗们的不开心程度的和最小。
题解
szm神犇说这是extend integer division,快d她
首先我们知道,贪婪值越大,饼干会越多,所以我们先从大到小排序
f[i][j]f[i][j]f[i][j]表示前i个人,分j个饼干,的最小不开心总和
若第i条狗的肉条>1,等价分配j−i个肉条给前i条狗,相对顺序不变,怨气总和不变
若第i个孩子只有一个饼干,那么枚举之前的多少孩子也获得一个饼干
所以可以得到dp式子

  1. f[i][j]=f[i][j−i]f[i][j]=f[i][j-i]f[i][j]=f[i][ji]
  2. f[i][j]=f[k][j−(i−k)]+∑p=k+1ia[p]f[i][j]=f[k][j-(i-k)]+\sum_{p=k+1}^ia[p]f[i][j]=f[k][j(ik)]+p=k+1ia[p]

输出方案的话,记录路径即可
效率O(n2m)O(n^2m)O(n2m)

#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,s[55],f[55][5005],a[55];
struct O{int g,d;}p[55],r[55][5005],h,l;
bool C(O x,O y){return x.g>y.g;}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=0;i<=n;i++) for (int j=0;j<=m;j++) f[i][j]=1e9;
    f[0][0]=0;for (int i=1;i<=n;i++) scanf("%d",&p[i].g),p[i].d=i;
    sort(p+1,p+n+1,C);for (int i=1;i<=n;i++) s[i]=s[i-1]+p[i].g;
    for (int i=1;i<=n;i++)
        for (int j=i;j<=m;j++){
            f[i][j]=f[i][j-i];r[i][j]=(O){i,j-i};
            for (int k=0;k<i;k++){
                int t=f[k][j-i+k]+k*(s[i]-s[k]);
                if (t<f[i][j]) f[i][j]=t,r[i][j]=(O){k,j-i+k};
            }
        }
    printf("%d\n",f[n][m]);h=(O){n,m};
    while(h.g && h.d){
        l=r[h.g][h.d];
        if (l.g==h.g) for (int i=1;i<=l.g;i++) a[p[i].d]++;
        else for (int i=l.g+1;i<=h.g;i++) a[p[i].d]++;
        h=l;
    }
    for (int i=1;i<=n;i++) printf("%d%c",a[i],i<n?' ':'\n');
    return 0;
}

T2:【from new_dtoj 停不下来的团长奥尔加(rideon)】
题目描述
暂无
题解
考场想到了状态,但是转移式子推错了,然后炸了boom
我写的是设f[i]表示第二次经过这个点需要的步数
那么首先我们要从i-1走过来,所以先是f[i-1]+1
然后我们发现他跳回p[i],然后因为这是一个类似前缀和的东西,所以我们应该加上一个f[i-1]-f[p[i]-1]
最后还要走一步,所以还要+1
所以f[i]=f[i-1]*2+f[p[i]-1]+2
注意特判p[i]=i的情况,即f[i]=2
效率O(n)O(n)O(n)

#include <cstdio>
const int N=1e6+5,P=1e9+7;
int n,p[N],f[N];
int main(){
    scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&p[i]);
    for (int i=1;i<=n;i++) f[i]=(2ll*f[i-1]+2-f[p[i]-1]+P)%P;
    return printf("%d\n",f[n]),0;
}

T3:【from new_dtoj 3996: Lesson5!(johnny)】
题目描述
暂无
题解
Johnny是我的英文名然鹅考场上对这题一点想法也没有
jarden:睡梦中想到的,G啊
楼上神犇写的博客,可神了
因为是DAG,所以我们可以跑两遍拓扑,求出从每个点出去和到每个点的最长路径f[ ]f[\ ]f[ ]g[ ]g[\ ]g[ ]
然后我们先把g[ ]g[\ ]g[ ]放到一棵权值线段树,然后每次按照拓扑序拿出一个x,把g[x]g[x]g[x]g[x]+f[y]+1g[x]+f[y]+1g[x]+f[y]+1(y指向x,边权为1)取出来
这个时候我们可以发现这个操作相当于x被删除了,所以我们求出线段树里面的最大下标,如果这个值比ans小即为答案
(也可以用别的喜欢的数据结构,例如multiset或者堆)
效率O(nlogn)O(nlogn)O(nlogn)

#include <cstdio>
#include <cstring>
#include <string>
#define _(d) while(d(isdigit(c=getchar())))
#define Ls k<<1
#define Rs Ls|1
using namespace std;
inline int R(){int x;char c;_(!);x=(c^48);_()x=(x<<3)+(x<<1)+(c^48);return x;}
const int N=1e5+5,M=5e5+5;
int T,n,m,in[N],ot[N],f[N],g[N],q[N],c,h,ans,id,s[N*4],ax[N*4];
struct O{
    int t,head[N],V[M],nex[M];
    inline void add(int u,int v){
        V[++t]=v;nex[t]=head[u];head[u]=t;
    }
}e1,e2;
inline void update(int k,int l,int r,int x,int v){
    if (l==r){
        s[k]+=v;
        if (s[k]>0) ax[k]=l;
        else ax[k]=-1,s[k]=0;
        return;
    }
    int mid=l+r>>1;
    if (mid>=x) update(Ls,l,mid,x,v);
    else update(Rs,mid+1,r,x,v);
    ax[k]=max(ax[Ls],ax[Rs]);
}
int main(){
    for (T=R();T--;){
        n=R();m=R();e1.t=e2.t=0;ans=1e9;
        memset(s,0,sizeof s);memset(ax,0,sizeof ax);
        for (int i=1;i<=n;i++) e1.head[i]=e2.head[i]=in[i]=ot[i]=g[i]=f[i]=0;
        for (int x,y,i=1;i<=m;i++)
            x=R(),y=R(),e1.add(x,y),e2.add(y,x),in[y]++,ot[x]++;
        c=0;h=1;for (int i=1;i<=n;i++) if (!ot[i]) q[++c]=i;
        while(h<=c){
            for (int i=e2.head[q[h]];i;i=e2.nex[i]){
                if (g[e2.V[i]]<g[q[h]]+1) g[e2.V[i]]=g[q[h]]+1;
                ot[e2.V[i]]--;if (!ot[e2.V[i]]) q[++c]=e2.V[i];
            }
            h++;
        }
        c=0;h=1;for (int i=1;i<=n;i++) if (!in[i]) q[++c]=i;
        while(h<=c){
            for (int i=e1.head[q[h]];i;i=e1.nex[i]){
                if (f[e1.V[i]]<f[q[h]]+1) f[e1.V[i]]=f[q[h]]+1;
                in[e1.V[i]]--;if (!in[e1.V[i]]) q[++c]=e1.V[i];
            }
            h++;
        }
        for (int i=1;i<=n;i++) update(1,0,n,g[i],1);
        for (int i=1;i<=n;i++){
            update(1,0,n,g[q[i]],-1);
            for (int j=e2.head[q[i]];j;j=e2.nex[j]) update(1,0,n,g[q[i]]+1+f[e2.V[j]],-1);
            if (ans>ax[1] || ans==ax[1] && id>q[i]) ans=ax[1],id=q[i];
            for (int j=e1.head[q[i]];j;j=e1.nex[j]) update(1,0,n,f[q[i]]+1+g[e1.V[j]],1);
            update(1,0,n,f[q[i]],1);
        }
        printf("%d %d\n",id,ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/xjqxjq/p/10544717.html


http://www.niftyadmin.cn/n/4556974.html

相关文章

编程高手进

首先你要弄明白的是&#xff1a;C语言是怎么工作的也就是说你写一段C语言代码会有什么样的效果&#xff08;等价于你说一名汉语是什么意思&#xff09; ||| 学习网站的话要有网站基础 里面高手如云 ||| 呵呵 分给我吧 51自学网 很不错 真的 里面什么都有 可以让你从入门到精通 …

mybatis开启驼峰转换

如果数据库中字段使用下划线作为分隔&#xff0c;而实体类属性用的小驼峰的方式命名&#xff0c;可以在mybatis的配置文件中开启驼峰转换 <setting name"mapUnderscoreToCamelCase" value"true"/>

2.redis集群搭建

集群模式下开启服务端 start-redis.sh 集群模式下开启客户端redis-cli -c -h 192.168.116.101 -p 7000集群模式下关闭服务端stop-redis.sh主从模式master -- slavekey&#xff1a; 互为副本存储hash 相当于分桶机制1.在 /soft/redis 目录 下suroot 用户 下2.mkdir conf cd c…

学习JAVA语言过程中遇到了一些问题

没有安当然不可以用 答案补充 QQ多少 看我能不能帮你 ||| 文档里没有写东西 html等等 我试过了可以啊 ||| 把那个文件直接改了扩展名就可以了 不行我再帮你看看 比如 你写了东西 在试这把HELLO该成小写 ||| 你在试试改成别的后缀名看会不会发生变化的 0KB 你什么都没有写 怎么编…

transition-

transition-timing-function&#xff1a;指定过渡速度曲线 ease&#xff08;默认&#xff09;&#xff1a;启动时为缓慢的转换效果&#xff0c;然后快速&#xff0c;缓慢结束 linear&#xff1a;从开始到结束具有相同速度的过渡效果 ease-in&#xff1a;慢速启动的过渡效果 eas…

先学C语言好还是先学JAVA好

fromuid29811 ||| 学C吧 不过 实际上我们现在学的很多语言都可以从c中找到影子啊 到时候高薪就业没问题 ||| java 大学里我们原来学C 后来都改了 不学C了 现在C不是最容易入门的了 ||| 如果不用来赚钱 java入门容易 JAVA的前途无量 祝你学成 我们老师现在就教我们的是JAVA u669…

2018-2019-1 20165326 《信息安全系统设计基础》第五周学习总结

第五周学习总结 目录 教材内容学习课下测试ch06总结 教材内容学习 存储技术 1. 随机访问存储器 静态RAM&#xff08;SRAM&#xff09;高速缓存存储器&#xff0c;既可以在CPU芯片上&#xff0c;也可以在片下双稳态存储单元&#xff0c;无限期地保持在两个不同电压配置或状态之一…