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的边最多能传递多少能量。

Output

最多能满足多少颗封印石的能量需求。

Sample Input


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,使得封印获得的总能量尽可能高。为了封印的最后一击尽量完美,就请你写个程序帮他计算一下吧!

Input

第一行一个整数N。

接下来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。

考场思路/正解

就是直接将它们的端点排一个序,然后可证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。

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。

考场思路

天啊,是字符串,于是我就放弃挣扎了。

正解

对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;
}

总结

还是感觉有种说不出的累。

明天也要加油鸭。。

 

猜你喜欢

转载自www.cnblogs.com/Thm-V/p/11374029.html