CodeChef - BLACKCOM 可行性dp转最优化树dp
https://www.codechef.com/problems/BLACKCOM
题意:一颗5000个黑白结点的树,10W个查询寻找是否存在大小s并且有t和黑节点的子图
一开始就觉得应当是一个树dp,但是总觉得怎么做怎么超时,用dp[5000][5000]预处理s大小t结点的可行性在时间复杂度上并不合理。
但是这题有一个结论,对于树上一个大小为s的子图而言,如果同时有可以存在r个黑色节点和l个黑色节点,则l - r之间的所有黑色节点都可以构造。
有了这个结论,就可以把dp方程转变为t结点的子树下大小为s最多的黑色和最少的黑色,然后取他们之间的值即可。
细节在于子树之间的处理,dfs的时候同一颗子树是不能将子图加起来的,需要另开一个数组更新当前子树对答案的更新结果,最后统一赋值给最终答案。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 5e3 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],tot;
void init(){
for(int i = ; i <= N ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int color[maxn];
int MAX[maxn][maxn],MIN[maxn][maxn];
int oMAX[maxn][maxn],oMIN[maxn][maxn];
int L[maxn],R[maxn],size[maxn];
void dfs(int t,int la){
MAX[t][] = MIN[t][] = color[t];
size[t] = ;
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == la) continue;
dfs(v,t);
for(int j = ; j <= size[t] + size[v]; j ++){
oMIN[t][j] = INF; oMAX[t][j] = ;
}
for(int p = ; p <= size[v]; p ++){
for(int q = ; q <= size[t]; q ++){
oMAX[t][p + q] = max(MAX[t][q] + MAX[v][p],oMAX[t][p + q]);
oMIN[t][p + q] = min(MIN[t][q] + MIN[v][p],oMIN[t][p + q]);
}
}
size[t] += size[v];
for(int p = ; p <= size[t]; p ++){
MAX[t][p] = oMAX[t][p];
MIN[t][p] = oMIN[t][p];
}
}
for(int i = ; i <= size[t]; i ++){
L[i] = min(L[i],MIN[t][i]);
R[i] = max(R[i],MAX[t][i]);
}
}
int main(){
int T; Sca(T);
while(T--){
Sca2(N,M);init();
for(int i = ; i <= N - ; i ++){
int u,v; Sca2(u,v);
add(u,v); add(v,u);
}
for(int i = ; i <= N ; i ++){
L[i] = INF; R[i] = -INF;
}
for(int i = ; i <= N ; i ++) Sca(color[i]);
dfs(,-);
for(int i = ; i <= M ; i ++){
int u,v; Sca2(u,v);
if(L[u] <= v && v <= R[u]) puts("Yes");
else puts("No");
}
}
return ;
}
CodeChef - BLACKCOM 可行性dp转最优化树dp的更多相关文章
- [BZOJ5287][HNOI2018]毒瘤(虚树DP)
		暴力枚举非树边取值做DP可得75. 注意到每次枚举出一个容斥状态的时候,都要做大量重复操作. 建立虚树,预处理出虚树上两点间的转移系数.也可动态DP解决. 树上倍增.动态DP.虚树DP似乎是这种问题的 ... 
- NOIP2011pj表达式的值[树形DP 笛卡尔树 | 栈 表达式解析]
		题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ... 
- CF456D A Lot of Games (字典树+DP)
		D - A Lot of Games CF#260 Div2 D题 CF#260 Div1 B题 Codeforces Round #260 CF455B D. A Lot of Games time ... 
- hdu 1520  Anniversary party 基础树dp
		Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ... 
- CodeForces 602E【概率DP】【树状数组优化】
		题意:有n个人进行m次比赛,每次比赛有一个排名,最后的排名是把所有排名都加起来然后找到比自己的分数绝对小的人数加一就是最终排名. 给了其中一个人的所有比赛的名次.求这个人最终排名的期望. 思路: 渣渣 ... 
- [CF 474E] Pillars (线段树+dp)
		题目链接:http://codeforces.com/contest/474/problem/F 意思是给你两个数n和d,下面给你n座山的高度. 一个人任意选择一座山作为起始点,向右跳,但是只能跳到高 ... 
- HDU4916 Count on the path(树dp??)
		这道题的题意其实有点略晦涩,定义f(a,b)为 minimum of vertices not on the path between vertices a and b. 其实它加一个minimum ... 
- Codeforces 219D. Choosing Capital for Treeland (树dp)
		题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ... 
- HDU4276 The Ghost Blows Light SPFA&&树dp
		题目的介绍以及思路完全参考了下面的博客:http://blog.csdn.net/acm_cxlove/article/details/7964739 做这道题主要是为了加强自己对SPFA的代码的训练 ... 
随机推荐
- How to execute a Stored Procedure with Entity Framework Code First
			Recently I worked on a project, which I started as code first and then I forced to switch to Databas ... 
- ES6字符串操作
			讨论字符串操作之前,我们先来了解一下Unicode 编码的由来,因为Js中的字符串就是一系列Unicode码的集合. 我们都知道,世界上存在着各种各样的语言,汉语,英语,日语等,相对应的,也就存在各种 ... 
- BZOJ3223文艺平衡树——非旋转treap
			此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ... 
- swagger2 如何匹配多个controller
			方法一:使用多个controller的共同拥有的父类,即精确到两个controller的上一级 @Bean public Docket createRestApi() { return new Doc ... 
- 手机Web 开发中图片img 如何等比例缩放
			如果图片本身没有设置 width.height属性的话,只需要修改 max-width:100%; 就可以了 如果图片本身设置了 width.height属性的话,需要同时修改width 和heigh ... 
- 前后端分离之vue2.0+webpack2 实战项目 -- html模板拼接
			对于前后端分离,如何把一个页面的公共部分比如head, header, footer, content等组合成一个完整的html 是一个值得考虑的地方. 对于php,我们可以利用include加载其他 ... 
- python学习日记(生成器函数进阶)
			迭代器和生成器的概念 迭代器 对于list.string.tuple.dict等这些容器对象,使用for循环遍历是很方便的.在后台for语句对容器对象调用iter()函数.iter()是python内 ... 
- 基数排序模板(基数排序,C++模板)
			算法的理论学习可右转Creeper_LKF大佬的洛谷日报 一个优化算法理论时间复杂度的实例点这里 另一个实例点这里 时间复杂度\(O(n)\),算常数的话要乘位长. 蒟蒻参考了Creeper_LKF大 ... 
- 「洛谷2495」「BZOJ3052」「SDOI2001」消耗战【虚树+树形动态规划】
			题目大意 给你\(k\)个点,让这一些点和一号节点断开,删去某一些边,求最小的删去边权之和. 做题的心路历程 做了\(HG\)昨天的模拟赛,深深感觉到了窝的菜,所以为了\(A\)掉T1这一道毒瘤,窝就 ... 
- 【转】VMware 全屏显示
			首先解决一个问题:配置虚拟机,发现屏幕大小太小 需要安装vmware tools ,屏幕就会自适应 但是安装vmware tools 的按钮是灰的,所以我首先就是安装它 [来源] 
