8.18 纪中集训 Day18
T1能量获取
Description
“封印大典启动,请出Nescafe魂珠!”随着圣主applepi一声令下,圣剑护法rainbow和魔杖护法freda将Nescafe魂珠放置于封印台上。封印台是一个树形的结构,魂珠放置的位置就是根节点(编号为0)。还有n个其他节点(编号1-n)上放置着封印石,编号为i的封印石需要从魂珠上获取Ei的能量。能量只能沿着树边从魂珠传向封印石,每条边有一个能够传递的能量上限Wi,魂珠的能量是无穷大的。作为封印开始前的准备工作,请你求出最多能满足多少颗封印台的能量需求?
注意:能量可以经过一个节点,不满足它的需求而传向下一个节点。每条边仅能传递一次能量。
注意:能量可以经过一个节点,不满足它的需求而传向下一个节点。每条边仅能传递一次能量。
Input
第一行一个整数n,表示除根节点之外的其他节点的数量。
接下来n行,第i+1行有三个整数Fi、Ei、Wi,分别表示i号节点的父节点、i号节点上封印石的能量需求、连接节点i与Fi的边最多能传递多少能量。
接下来n行,第i+1行有三个整数Fi、Ei、Wi,分别表示i号节点的父节点、i号节点上封印石的能量需求、连接节点i与Fi的边最多能传递多少能量。
Output
最多能满足多少颗封印石的能量需求。
Sample Input
4
0 3 2
0 100 100
1 1 1
2 75 80
Sample Output
2
Data Constraint
对于100%的数据,满足1<=n<=1000,0<=Fi<=n,0<=Ei,Wi<=100
考场思路/正解
细读题目,不然发现,每一个节点如果能到达根,它们的贡献是一样的,所以我们只要每次去判断代价最小的节点能否到达根,如果可以,ans就++。
Code
#include<cstdio> #include<algorithm> using namespace std; int n,ans; struct thm { int zhi; int id; }sz[1010]; struct TREE { int fa; int e; int w; }tree[1010]; bool cmp(thm a,thm b) <%return a.zhi<b.zhi;%>; bool check(int id,int k) { if(id==0) return true; if(tree[id].w>=k && check(tree[id].fa,k)) { tree[id].w-=k; return true; } else return false; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d%d",&tree[i].fa,&tree[i].e,&tree[i].w); sz[i].id=i,sz[i].zhi=tree[i].e; } sort(sz+1,sz+1+n,cmp); for(int i=1;i<=n;i++) { if(check(sz[i].id,sz[i].zhi)) ans++; } printf("%d",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,使得封印获得的总能量尽可能高。为了封印的最后一击尽量完美,就请你写个程序帮他计算一下吧!
Input
第一行一个整数N。
接下来N行每行两个整数ai、bi,第i+1行表示第i种元素的封印区间。
接下来N行每行两个整数ai、bi,第i+1行表示第i种元素的封印区间。
Output
两个用空格隔开的证书,第一个数十能够获得最多总能量的封印力度E,第二个数是获得的总能量大小。当存在多个E能够获得最多总能量时,输出最小的E。
Sample Input
2
5 10
20 25
Sample Output
10 30
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。
考场思路/正解
就是直接将它们的端点排一个序,然后可证E的位置一定在某个右端点上,然后在巧妙的处理一下就行了。
Code
#include<cstdio> #include<algorithm> #define LL long long using namespace std; LL n,a,b,sl,qzh,jl,ans,zx; struct thm { LL v; int pd; }sz[200020]; bool cmp(thm a,thm b) <%return a.v<b.v;%> int main() { scanf("%lld",&n); for(LL i=1;i<=n;i++) { scanf("%lld%lld",&a,&b); sz[++sl].v=a; sz[++sl].v=b;sz[sl].pd=1; qzh+=a; } sort(sz+1,sz+1+sl,cmp); for(LL i=1;i<=sl;i++) { if(!sz[i].pd) { qzh-=sz[i].v; jl++; } else { if(qzh+jl*sz[i].v>ans) ans=qzh+jl*sz[i].v,zx=sz[i].v; jl--; } } printf("%lld %lld",zx,ans); return 0; }
T3归途与征程
Description
Input
第一行为字符串A。
第二行为字符串B。
第二行为字符串B。
Output
输出在B的所有循环同构串中,有多少个能够与A匹配。
Sample Input
输入1:
aaaa
aaaa
输入2:
a*a
aaaaaa
输入3:
*a*b*c*
abacabadabacaba
Sample Output
输出1:
4
输出2:
6
输出3:
15
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。
考场思路
天啊,是字符串,于是我就放弃挣扎了。
正解
对KMP的一个高级应用。。
Code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int len1,len2,sl,k,zx,end,ans; int cnt[110],Next[110][110],nt[110][200020]; char s1[110],s2[200020],ch[110][110]; int main() { scanf("%s%s",s1+1,s2+1); len1=strlen(s1+1);len2=strlen(s2+1); for(int i=1;i<=len2;i++) s2[i+len2]=s2[i]; for(int i=1;i<=len1;i++) { while(i<=len1 && s1[i]=='*') i++; sl++; while(i<=len1 && s1[i]!='*') { ch[sl][++cnt[sl]]=s1[i]; i++; } } for(int i=1;i<=sl;i++) { k=0; for(int j=2;j<=cnt[i];j++) { while(k && ch[i][k]!=ch[i][j]) k=Next[i][k]; if(ch[i][k+1]==ch[i][j]) k++; Next[i][j]=k; } } for(int i=1;i<=sl;i++) { k=0; for(int j=1;j<=2*len2;j++) { while(k && ch[i][k+1]!=s2[j]) k=Next[i][k]; if(ch[i][k+1]==s2[j]) k++; if(k!=cnt[i]) continue; zx=j-cnt[i]+1; while(zx && !nt[i][zx]) { nt[i][zx]=j; zx--; } k=Next[i][k]; } } for(int i=1;i<=len2;i++) { end=i+len2-1;k=1;zx=i-1; if(s1[1]!='*' && i+cnt[k]-1!=nt[k][i]) continue; while(zx<=end && k<=sl) { zx++; zx=nt[k][zx]; if(!zx) break; k++; } if(s1[len1]=='*') { if(zx<=end && sl+1==k) ans++; } else { if(sl+1!=k) continue; while(zx<end && zx) zx=nt[k-1][zx-cnt[k-1]+2]; ans+=zx==end; } } printf("%d",ans); return 0; }
总结
还是感觉有种说不出的累。
明天也要加油鸭。。