题目:F. Maximum White Subtree
题意:给定一棵树,节点只为黑或者白,问每一个节点的的子树(连通块)中max(白节点个数-黑节点的个数);
把白节点的的值定1,黑的为-1,即计算价值最大,树形dp,联系子,父节点的关系,可直接以i为根进行dp,dp1[i]表示以i为父节点向下max(白-黑),先从下至上做一个dp1记录子节点的max;
还有节点的父节点这边的最大连通块没有确定,比方说val是通过父节点的获得的价值,val<=0的时候表示没有必要加入他的价值给子节点,val>0的时候加入增加子节点的价值,而dp1[i]负数最大就是自己本身-1是一定要算的,进而加上dp1[root]即可。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
int a[200100];
bool vis[200100];
vector<int>hh[200100];
int dp1[200100];
int dp2[200100];
void dfs1(int root,int fa)
{
if(vis[root])
return ;
vis[root]=true;
dp1[root]=a[root];
for(int i=0;i<hh[root].size();i++)
{
int v=hh[root][i];
if(v!=fa&&!vis[v])
{
dfs1(v,root);
dp1[root]+=max(0,dp1[v]);
}
}
}
void dfs2(int root,int fa)
{
if(vis[root])
return ;
vis[root]=true;
dp2[root]=dp1[root]+max(0,dp2[fa]-max(0,dp1[root]));
for(int i=0;i<hh[root].size();i++)
{
int v=hh[root][i];
if(v!=fa&&!vis[v])
{
dfs2(v,root);
}
}
}
int main()
{
int n,i,j,l,r,h;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i])
a[i]=1;
else
a[i]=-1;
}
for(i=1;i<=n-1;i++)
{
int x,y;
scanf("%d %d",&x,&y);
hh[x].push_back(y);
hh[y].push_back(x);
}
memset(vis,false,sizeof(vis));
dfs1(1,-1);
memset(vis,false,sizeof(vis));
dfs2(1,-1);
for(i=1;i<=n;i++)
{
printf("%d ",dp2[i]);
}
return 0;
}
题目:E. Sleeping Schedule
题意:有n个睡眠时间的选择,可以选择a[i]或者a[i]-1 小时之后开始睡觉,如果在l-r时间段开始睡觉则是好的睡眠,一睡h小时(也就是一天)。
一开始想用a[i]或者a[i]-1状态去进行dp,但是发现状态存储情况比较多,可以看到h(一天有h小时)并不大,将二维的状态改成h就可以了。
dp[i][j]:表示第i次 开始睡眠在j时的时候的好睡眠次数最大值。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
int a[2010];
int dp[2010][2010];
int book[2010];
int main()
{
memset(book,0,sizeof(book));
memset(dp,0,sizeof(dp));
int n,i,j,l,r,h;
scanf("%d %d %d %d",&n,&h,&l,&r);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
int ans=0;
dp[0][0]=1;
for(i=1;i<=n;i++)
{
for(j=0;j<h;j++)
{
if(dp[i-1][j])
{
bool flag=false;
int temp;
temp=(j+a[i])%h;
if(temp>=l&&temp<=r)
dp[i][temp]=max(dp[i][temp],dp[i-1][j]+1);
else
dp[i][temp]=max(dp[i][temp],dp[i-1][j]);
temp=(j+a[i]-1)%h;
if(temp>=l&&temp<=r)
dp[i][temp]=max(dp[i][temp],dp[i-1][j]+1);
else
dp[i][temp]=max(dp[i][temp],dp[i-1][j]);
}
}
}
for(i=0;i<h;i++)
ans=max(ans,dp[n][i]);
printf("%d",ans-1);
return 0;
}