• CF559E Gerald and Path


    题目链接

    没看懂题解,但是大概知道它的思路了,然后自己造了一种实现方式。

    首先按照那个点从小到大排序。设 (f_{i,j,t}) 表示考虑了前 (i) 个线段,最靠右的线段为第 (j) 个且方向为 (t)(0左1右),的最大覆盖长度。转移就多考虑一个线段,考虑要不要选它,方向是啥,随便DP一下就好了。

    for (int i = 1; i <= n; ++i) {
    	memcpy(f[i], f[i - 1], sizeof(f[i]));
    	for (int np = 0; np < 2; ++np) {
    		for (int j = 0; j < i; ++j) {
    			for (int p = 0; p < 2; ++p) {
    				int nwp = S[i].p, nwlen = S[i].l;
    				int lstp = S[j].p, lstlen = S[j].l;
    				int nwr = nwp + (np == 1 ? nwlen : 0);
    				int lstr = lstp + (p == 1 ? lstlen : 0);
    				int nwl = nwr - nwlen;
    				if (lstr > nwr)	continue;
    				int res = f[i - 1][j][p];
    				if (nwl >= lstr) res += nwlen;
    				else	res += nwr - lstr;
    				MAX(f[i][i][np], res);
    				MAX(ans, res);
    			}
    		}
    	}
    } 
    

    然后发现过不了样例。而反例仅有:

    反例

    算红色的线的时候它明明能够多覆盖左边的一篇区域,结果我们认为它“无用”,扔掉了它。而这种情况只有 之前线段向右,当前线段向左 才会发生。于是考虑按块转移,将这种情况从这几个线段前直接转移到当前线段。我们只需要知道黑色线段的右端点最大值即可。

    有一些细节,各种情况要特判一下。

    复杂度:(O(n^3))

    for (int i = 1; i <= n; ++i) {
    	memcpy(f[i], f[i - 1], sizeof(f[i]));
    	for (int np = 0; np < 2; ++np) {
    		for (int j = 0; j < i; ++j) {
    			for (int p = 0; p < 2; ++p) {
    				int nwp = S[i].p, nwlen = S[i].l;
    				int lstp = S[j].p, lstlen = S[j].l;
    				int nwr = nwp + (np == 1 ? nwlen : 0);
    				int lstr = lstp + (p == 1 ? lstlen : 0);
    				int nwl = nwr - nwlen;
    				if (lstr > nwr)	continue;
    				int res = f[i - 1][j][p];
    				if (nwl >= lstr) res += nwlen;
    				else	res += nwr - lstr;
    				MAX(f[i][i][np], res);
    				MAX(ans, res);
    			}
    		}
    	}
    	int mxr = -inf, whic = 0;
    	for (int j = i - 1; j; --j) {
    		int r = S[j].p + S[j].l;
    		if (r > mxr)	mxr = r, whic = j;
    		if (mxr <= S[i].p)	continue;
    		for (int k = j - 1; ~k; --k) {
    			for (int t = 0; t < 2; ++t) {
    				int lstr = S[k].p + (t == 1 ? S[k].l : 0);
    				if (lstr >= S[i].p)	continue;
    				int tmp = mxr - max(S[i].p - S[i].l, lstr);
    				MAX(f[i][whic][1], f[j - 1][k][t] + tmp);
    				MAX(ans, f[i][whic][1]);
    			}
    		}
    	}
    }
    
  • 相关阅读:
    SQL大全基本语法
    ASP.NET实现二维码
    JMeter下载及安装配置完整版
    windows下搭建nginx负载均衡
    C# 接口生成工具Swagger用法
    在IIS上部署网站,应用程序池选择.Net Framework版本为 v4.0.30319后,打开网站报错
    sqlserver 中WITH NOLOCK、HOLDLOCK、UPDLOCK、TABLOCK、TABLOCKX
    C#进阶学习笔记
    C#单例模式的理解
    实现WebService只返还json结构数据
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13729165.html
Copyright © 2020-2023  润新知