zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 117

    D - Miracle Tree

    由于是无根树,所以找一个根,设 (E_{rt}=1) .

    对于两条叶子到根的链,它们受到根的距离的约束必然没有互相之间距离的约束大,所以标法必然是维护一个时间,DFS 整棵树,在一个节点进栈的时候时间 (+1) ,出栈的时候时间 (+1) ,然后一个节点的 (E_u) 为进栈时间。

    然后会发现最大的标号的节点(终止节点) (v) 的标号是 (2n−dep[v]) 。所以根和终止节点取直径的两端即可。

    From George1123

    void Adde( int u,int v ) { g[u].push_back(v); g[v].push_back(u); }
    bool cmp( int x,int y ) { return height[x]<height[y]; }
    void DFS( int u,int fat )
    {
    	for ( int v : g[u] )
    		if ( v^fat ) dep[v]=dep[u]+1,DFS(v,u);
    }
    void DFS2( int u,int fat )
    {
    	height[u]=0;
    	for ( int v : g[u] ) 
    		if ( v^fat ) DFS2(v,u),bmax(height[u],height[v]);
    	height[u]++;
    }
    void GetAns( int u,int fat )
    {
    	ans[u]=++cnt;
    	for ( int v : g[u] )
    		if ( v^fat ) GetAns(v,u);
    	cnt++;
    }
    
    int main()
    {
    //freopen( "exam.in","r",stdin );
    
    	n=read();
    	for ( int i=1,u,v; i<n; i++ ) u=read(),v=read(),Adde(u,v);
    
    	DFS(1,0); int tmp=0;
    	for ( int i=1; i<=n; i++ ) if ( dep[i]>tmp ) tmp=dep[i],rt=i;
    	DFS2(rt,0);
    	for ( int i=1; i<=n; i++ ) sort(g[i].begin(),g[i].end(),cmp);
    	GetAns(rt,0);
    
    	for ( int i=1; i<=n; i++ ) printf("%d ",ans[i] );
    
    	return 0;
    }
    

    E - Zero-Sum Ranges 2

    AtCoder 常见毒瘤 DP。

    首先显然转化为前缀和,某个区间 ((l,r]) 和为 (0) 就是 (s[r]=s[l]) ,也就是统计相等的对数。

    由于元素只有 (pm 1) ,所以画成图像一定是类似这种东西:

    那么考虑按层从上往下 DP。注意到两个 (s[i]) 相等的位置必然不相邻,并且两个位置中间都是一个峰或者坑。设 (dp[i][j][k]) 表示当前有 (i) 个数,形成的相等对(就是 (s[i]=s[j]) )有 (j) 个,相邻两个 (s[i]) 相等的位置有 (k) 个(这些由于不能相邻,中间一定要填更小的数,下面称之为要填的坑)。

    考虑转移,(dp[i][j][k] o dp[i+x][j+frac{x(x-1)}2][x-(k+2)])(x-(k+2)) 是因为在用新的数填了之前的坑和整个序列两端之后少了 (k+2) 个,剩下的形成了新的坑。根据隔板法不难得到要乘上组合数 (displaystyleinom{x-1}{k+1}) .

    统计答案时,按照 (0) 层分开,把地上和地下的合并即可,也就是 (dp[x][y][z] imes dp[(2n+1)-x][k-y][z-1]) . ( (2n+1) 是补了 (s[0])

    //Author: RingweEH
    signed main()
    {
    //freopen( "exam.in","r",stdin );
    
    	int n=read(),k=read(); C_Init();
    	for ( int i=1; i<=n+1 && i*(i-1)/2<=k; i++ ) dp[i][i*(i-1)/2][i-1]=1;
    	for ( int i=1; i<=2*n+1; i++ )
    		for ( int j=0; j<=k; j++ )
    			for ( int l=0; l<=n; l++ )
    			{
    				if ( dp[i][j][l]==0 ) continue;
    				for ( int x=l+2; i+x<=2*n+1 && x<=n+1; x++ )
    				{
    					int nxt=j+x*(x-1)/2; if ( nxt>k ) break;
    					dp[i+x][nxt][x-(l+2)]+=dp[i][j][l]*C[x-1][l+1];
    				}
    			}
    	int ans=dp[2*n+1][k][0];
    	for ( int i=0; i<=2*n+1; i++ )
    		for ( int j=0; j<=k; j++ )
    			for ( int l=1; l<=n; l++ )
    				ans+=dp[i][j][l]*dp[(2*n+1)-i][k-j][l-1];
    
    	printf("%lld
    ",ans );
    
    	return 0;
    }
    

    F - Gateau

    • (forall 0leq i<n,a_ileq sum_{j=0}^{n-1}b_{i+j})
    • (forall nleq i<2n,a_ileqsum_{j=i}^{2n-1}b_j+sum_{j=0}^{i-n-1}b_j) ,设 (X=sum b_i) ,就是 (sum_{j=i-n}^{i-1}b_jleq X-a_i)

    (s_i=sum_{j=0}^{i-1}b_j) ,那么 (a_ileq s_{i+n}-s_ileq X-a_{i+n}) ,且 (s_ileq s_{i+1}) ,问题转化为判定形式。显然可以写成差分约束的形式,建有向边 ((i,j,x))(0) 开始求最长路即可,如果有正环或者 (d_{2n-1}>X) 误解。

    直接 SPFA 会被卡,考虑特殊性质。如果删去 ((n-1,n,0)) ,那么图为两行 ([0,n),[n,2n)) 。如果把两个对应点的最长路一起算,没有后效性,可以 (O(n)) 求。加入这条边之后,用 (s_{n-1}) 更新 (s_n) 并再求一次最长路,如果 (s_{n-1}) 变化就有正环,否则求出了最长路。

    //Author: RingweEH
    void Calc( ll x )
    {
        for ( int i=1; i<n; i++ )
            dis[i]=max(dis[i-1],dis[i+n-1]+a[i+n]-x),
            dis[i+n]=max(dis[i+n-1],dis[i-1]+a[i]);
    }
    
    bool Check( ll x )
    {
        for ( int i=0; i<n; i++ ) if ( a[i]+a[i+n]>x ) return 0;
        dis[n]=a[0]; Calc(x);
        ll las=dis[n-1]; dis[n]=max(dis[n],dis[n-1]);
        if ( dis[n]>x-a[n] ) return 0;
        Calc(x);
        if ( las^dis[n-1] ) return 0;
        return dis[2*n-1]<=x;
    }
    
    int main()
    {
    //freopen( "exam.in","r",stdin );
    
        n=read();
        for ( int i=0; i<2*n; i++ ) a[i]=read();
    
        ll l=0,r=1e15;
        while ( l<r )
        {
            ll mid=(l+r)>>1;
            if ( Check(mid) ) r=mid;
            else l=mid+1;
        }
    
        printf("%lld
    ",l );
    
        return 0;
    }
    
    天光渐亮。
  • 相关阅读:
    Springboot+resteasy定时任务
    MySql COUNT(),SUM()组合用法
    MySql按每日、每周、每月分组统计数据
    阿里云通过访问地址来缩小图片,减少流量消耗
    ExtJs6获取form里的数据
    postfix中recipient/client/sender/helo四者的区别<转载>
    用telnet命令,POP3接收邮件
    用telnet命令,SMTP发送邮件
    Linux 标准目录结构
    centos minimal Bind 主从服务器部署
  • 原文地址:https://www.cnblogs.com/UntitledCpp/p/ARC117.html
Copyright © 2011-2022 走看看