T1
Description
“封印大典启动,请出Nescafe魂珠!”随着圣主applepi一声令下,圣剑护法rainbow和魔杖护法freda将Nescafe魂珠放置于封印台上。封印台是一个树形的结构,魂珠放置的位置就是根节点(编号为0)。还有n个其他节点(编号1-n)上放置着封印石,编号为i的封印石需要从魂珠上获取Ei的能量。能量只能沿着树边从魂珠传向封印石,每条边有一个能够传递的能量上限Wi,魂珠的能量是无穷大的。作为封印开始前的准备工作,请你求出最多能满足多少颗封印台的能量需求?
注意:能量可以经过一个节点,不满足它的需求而传向下一个节点。每条边仅能传递一次能量。
注意:能量可以经过一个节点,不满足它的需求而传向下一个节点。每条边仅能传递一次能量。
Data Constraint
对于100%的数据,满足1<=n<=1000,0<=Fi<=n,0<=Ei,Wi<=100
Solution:
考虑树形dp,把每个点的需求抽象为代价,即可转化为背包问题
设Dp[i][j]表示根为i的子树下花费j点能量可以满足的最多点
然后背包转移即可
考场因为不熟练写挂了,遗憾
貌似贪心取最小点也可以A
Code:
#include<bits/stdc++.h>
using namespace std;
#define re register
inline int MAX(int a,int b)<% return (a>b)?a:b; %>
int N,son[1005][1005],tot[1005],E[1005],W[1005],Fa[1005],Ans;
int Dp[1005][105];//Dp[i][j]表示根为i的子树下花费j点能量可以满足的最多点
void dfs(int Pos){
for(int i=E[Pos];i<=W[Pos];i++) Dp[Pos][i]=1;
if(tot[Pos]==0) return;
for(re int i=1;i<=tot[Pos];++i){
dfs(son[Pos][i]);
}
for(re int i=1;i<=tot[Pos];i++){
for(re int j=W[Pos];j>=0;j--)
for(re int k=0;k<=W[son[Pos][i]]&&j>=k;k++)
Dp[Pos][j]=MAX(Dp[Pos][j-k]+Dp[son[Pos][i]][k],Dp[Pos][j]);
}
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;i++){
scanf("%d",&Fa[i]);
scanf("%d%d",&E[i],&W[i]);
son[Fa[i]][++tot[Fa[i]]]=i;
if(Fa[i]==0) W[0]+=W[i];
}
for(int i=1;i<=tot[0];i++){
dfs(son[0][i]);
Ans+=Dp[son[0][i]][W[son[0][i]]];
}
cout<<Ans;
return 0;
}
T2
Description
“圣主applepi于公元2011年9月创造了Nescafe,它在散发了16吃光辉之后与公元2011年11月12日被封印为一颗魂珠,贮藏于Nescafe神塔之中。公元2012年9月,圣主带领四大护法重启了Nescafe,如今已经是Nescafe之魂的第30吃传播了。不久,它就要被第二次封印,而变成一座神杯。。。”applepi思索着Nescafe的历史,准备着第二次封印。
Nescafe由n种元素组成(编号为1~n),第i种元素有一个封印区[ai,bi]。当封印力度E小于ai时,该元素获得ai的封印能量;当封印力度E在ai到bi之间时,该元素将获得E的封印能量;而当封印力度E大于bi时,该元素将被破坏从而不能获得任何封印能量。现在圣主applepi想选择恰当的E,使得封印获得的总能量尽可能高。为了封印的最后一击尽量完美,就请你写个程序帮他计算一下吧!
Nescafe由n种元素组成(编号为1~n),第i种元素有一个封印区[ai,bi]。当封印力度E小于ai时,该元素获得ai的封印能量;当封印力度E在ai到bi之间时,该元素将获得E的封印能量;而当封印力度E大于bi时,该元素将被破坏从而不能获得任何封印能量。现在圣主applepi想选择恰当的E,使得封印获得的总能量尽可能高。为了封印的最后一击尽量完美,就请你写个程序帮他计算一下吧!
Data Constraint
对于50%的数据,1<=N<=1000,1<=ai<=bi<=10000。
对于100%的数据,1<=N<=10^5,1<=ai<=bi<=10^9。
对于100%的数据,1<=N<=10^5,1<=ai<=bi<=10^9。
Solution:
因为玄学的原因所以结果肯定是某个端点??
排序之后从小到大进行枚举即可,处理结果巧妙使用两个P1和P2(详见代码)。
Code:
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
int A[100500],tot,B[100500],Pos,N;
LL P1,P2;
struct Node
{
LL Val,prio;
}C[100500*2];
LL Ans;
int cmp(Node a,Node b){
return a.Val<b.Val||(a.Val==b.Val&&a.prio>b.prio);
}
int main()
{
Ans=-1e9-7;
scanf("%d",&N);
for(int i=1;i<=N;i++){
scanf("%d%d",&A[i],&B[i]);
P1+=A[i];
C[++tot].Val=A[i];C[tot].prio=1;
C[++tot].Val=B[i];C[tot].prio=0;
}
sort(C+1,C+tot+1,cmp);
for(int i=1;i<=tot;i++)
if(C[i].prio==1){
P1-=C[i].Val;P2++;
LL Sum=1ll*C[i].Val*P2+1ll*P1;
if(Ans<Sum) <%Ans=Sum; Pos=C[i].Val; %>
}
else {
LL Sum=1ll*C[i].Val*P2+1ll*P1;
if(Ans<Sum) <%Ans=Sum; Pos=C[i].Val; %>
P2--;
}
printf("%d %lld",Pos,Ans);
return 0;
}
T3
Description:
Data Constraint
对于30%的数据,M<=20;
对于80%的测试点,M<=200;
对于100%的测试点,1<=N<=100,1<=M<=100000。
对于80%的测试点,M<=200;
对于100%的测试点,1<=N<=100,1<=M<=100000。
Solution:
80分把每个*看做分隔符然后按顺序匹配同时枚举m次来表示不同的循环同构串。
100分未知
Code:(80分啥都写了结果匹配忘记怎么写了我丢人我自闭)