zoukankan      html  css  js  c++  java
  • 8.20 附加赛3


    2018.8.20 附加赛3

    比赛链接

    A 斯(贪心)

    题目链接

    某状态下的最差情况收益就是min(wa,wb)-cost。当然是从大的取,同时尽量保证wa,wb均衡。
    枚举一下,Ans时刻取个max就行了。
    复杂度在于排序 O(nlogn)。Ai只有四位小数且<=10,可以用桶排降到O(n)。

    //138ms	2392kb
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    //#define gc() getchar()
    #define MAXIN 300000
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    const int N=1e5+5;
    
    int n;
    double A[N],B[N];
    char IN[MAXIN],*SS=IN,*TT=IN;
    
    inline double read()
    {
    	double x=0,y=0.1; register char c=gc();
    	for(; !isdigit(c)&&c!='.'; c=gc());
    	for(; isdigit(c); x=x*10+c-'0',c=gc());
    	for(c=='.'&&(c=gc()); isdigit(c); x+=(c-'0')*y,y*=0.1,c=gc());
    	return x;
    }
    
    int main()
    {
    	n=read();
    	for(int i=1; i<=n; ++i) A[i]=read();
    	for(int i=1; i<=n; ++i) B[i]=read();
    	std::sort(A+1,A+1+n), std::sort(B+1,B+1+n);
    	double Ans=0,nowa=0,nowb=0;
    	for(int a=n,b=n,cost=0; a||b; ++cost,Ans=std::max(Ans,std::min(nowa,nowb)-cost))
    	{
    		if(!b||(nowa<=nowb && a)) nowa+=A[a--];
    		else nowb+=B[b--];
    	}
    	printf("%.4lf
    ",Ans);
    
    	return 0;
    }
    

    B 给(DP)

    题目链接

    DP,f[i][j]表示当前有i个叶子,树中根到所有叶子的路径中向左的边都不超过j条,的方案数。
    根节点的两棵左右子树算是两个独立的子问题,即枚举左子树的叶节点数k后,可以直接f[k]*f[i-k]拼起来。
    再具体就是左子树中所有向左边不超过j-1条的叶节点都可以接上i,然后乘上右子树所有路径向左边不超过j条的方案数。
    (f[i][j]=sum_{k=1}^{j-1}f[k][j-1]*f[i-k][j])
    至于为什么只枚举左儿子而不用*2。。不知道。。求dalao解答。。(枚举是对称的?)
    这样是O(n^3),得分35~40。
    注意到转移是个卷积形式,用NTT转移 写的好的话能拿到60。

    满分做法:还是要换种状态表示,考虑枚举一个一个放叶子:f[i][j]表示已有i个叶子,当前放的叶子到根节点的路径有j条向左边。
    下一个点要么放在当前叶子的左儿子。这样不会改变叶子数,j要加1,即转移到f[i][j+1]。
    要么放在最近有左儿子但是没放右儿子的点,作为其右儿子。这样能转移到叶子数+1,j-1的状态,即f[i+1][j-1]。
    f[i][0]就表示已有i个叶子,且所有有左儿子的点都有右儿子了,即k=i时的答案。
    因为是枚举了所有状态下的唯二两种转移。。嗯。。所以说(这么说)没问题吧。。
    复杂度O(n^2)。

    唉 感觉两个DP都好迷啊。。

    //376ms	95800kb(莫名慢好多 明明都差不多)
    #include <cstdio>
    #define mod (998244353)
    #define rg register
    //#define Add(x,v) x+=v,x>=mod&&(x-=mod)
    const int N=5005;
    
    int f[N][N];
    inline void Add(int &x,int v){
    	x+=v, x>=mod&&(x-=mod);
    }
    
    int main()
    {
    	int m,n; scanf("%d%d",&m,&n);
    	f[1][0]=1;
    	for(rg int i=1; i<n; ++i)
    	{
    		Add(f[i][1],f[i][0]);
    		for(rg int j=1; j<m; ++j)
    			Add(f[i][j+1],f[i][j]), Add(f[i+1][j-1],f[i][j]);
    	}
    	for(rg int i=1; i<=n; ++i) printf("%d
    ",f[i][0]);
    
    	return 0;
    }
    

    C 普

    题目链接

    
    
  • 相关阅读:
    请求页面
    获取iframe内的元素
    jquery 判断checkbox是否被选中问题
    bootStrap 模板地址
    content
    基于JS的文本验证
    canvas 移动光速特效-
    Swift 语法
    Xcode 8 Swift 类似插件方法
    js整频滚动展示效果(函数节流鼠标滚轮事件)
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9524754.html
Copyright © 2011-2022 走看看