欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

day18

程序员文章站 2022-08-02 10:38:36
今天的题好难啊!!!!80/300; T1第一眼像个树形DP,推了大约30min无果,改写暴力还写挂了!!!!0/100 正解:贪心,每次选最小的花费,向上更新看是否合法; #include #include #include #include

今天的题好难啊!!!!80/300;

t1第一眼像个树形dp,推了大约30min无果,改写暴力还写挂了!!!!0/100

正解:贪心,每次选最小的花费,向上更新看是否合法;

#include<iostream>
#include<cstdio>
#include<vector>
#include<cctype>
#include<algorithm>
using namespace std;
struct node{
    int e,fa;
}a[1010];
int fa[1010],w[1010];
int n,ans,total;
bool v;
inline int cmp(node x,node y){return x.e<y.e;}
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    return x*f;
}
inline void check(int x,int i)
{
    if(i==0)return;
    if(w[i]>=x)
    {
        check(x,fa[i]);
    }
    else
    {
        v=0;
        return;
    }
}
inline void updata(int x,int i)
{
    if(i==0)return;
    w[i]-=x;
    updata(x,fa[i]);
}
int main()
{
    n=read(); 
    for(int i=1;i<=n;i++)
    {
        fa[i]=read();a[i].e=read();w[i]=read();
        a[i].fa=i;
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
    {
        v=1;
        check(a[i].e,a[i].fa);
        if(v){total++;updata(a[i].e,a[i].fa);}
    }
    cout<<total<<endl;
    return 0;
}

t2发现答案只在右端点,写了一个o(n/2+n2/2)的算法,拿了60分(吸一口氧可拿80)60/100

 正解,把 l 和 r 丢到一个数组中排序,处理一个 sa 记录全部 l 的和,sp 记录现在在几个区间中,

遇到一个 l 端点 sa--,sp++;遇到一个 r 端点 先判断是否要更新答案,然后 sp--;复杂度极低;

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
    long long l,r;
}c[210000];
int n,l[110000],r[110000];
inline long long maxx(long long x,long long y){return x>y?x:y;}
inline int cmp(node x,node y)
{
    return x.l<y.l;
}
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    return x*f;
}
int main()
{
    n=read();long long sa=0,sp=0,ans1,ans=-1;
    for(int i=1;i<=n;i++)
    {
        l[i]=read();r[i]=read();
        sa+=l[i];
        c[i].l=l[i];c[i+n].r=1;
        c[i+n].l=r[i];
    }
    sort(c+1,c+1+2*n,cmp);
    for(int i=1;i<=2*n;i++)
    {
        if(c[i].r)
        {
            if(ans<sa+sp*c[i].l){
                ans1=c[i].l;ans=sa+sp*c[i].l;
            }
            sp--;
        }
        if(!c[i].r)
        {
            sa-=c[i].l;sp++;
        }
    }
    cout<<ans1<<" "<<ans<<endl;
    return 0;
}

t3写了一个暴力匹配结果炸了???20/100

把a串以*分割成几个子串,b串*2处理循环,在kmp搞一下,记录以某个字符为起点能匹配完a的某个子串的最近位置。

然后再扫一遍就行了。

#include<bits/stdc++.h>
using namespace std;
char a[200],b[210000],c[110][110];
int n,m,ans,next[101][101],first[51][200001],last[200001],v,gs[101];
int main()
{
    scanf("%s%s",a+1,b+1);
    n=strlen(a+1);m=strlen(b+1);
    for(int i=1;i<=n;i++)
    {
        while(a[i]=='*')
        i++;
        gs[0]++;
        while(a[i]!='*'&&i<=n)
        {
            c[gs[0]][++gs[gs[0]]]=a[i];
            i++;
        }
    }
    if(gs[0]==1&&n!=m)
    {
        cout<<'0'<<endl;
        return 0;
    }
    for(int i=1;i<m;i++)
        b[i+m]=b[i];
    for(int i=1;i<=gs[0];i++)
    {
        int k=0;
        for(int j=2;j<=gs[i];j++)
        {
            while(c[i][j]!=c[i][k+1]&&k)k=next[i][k];
            if(c[i][j]==c[i][k+1])k++;
            next[i][j]=k;
        }
    }
    for(int i=1;i<=gs[0];i++)
    {
        int k=0;
        for(int j=1;j<=2*m;j++)
        {
            while(k&&c[i][k+1]!=b[j])k=next[i][k];
            if(c[i][k+1]==b[j])k++;
            if(i==gs[0])last[j]=k;
            if(k==gs[i]){
                int l=j-k+1;
                while(l&&!first[i][l])
                {
                    first[i][l]=j;
                    l--;
                }
                k=next[i][k];
            }
        }
    }
    for(int i=1;i<=m;i++)
    {
        int r=i+m-1,l=i-1,g=1;
        if(a[1]!='*'&&i+gs[g]-1!=first[g][i])continue;
        while(l<=r&&g<=gs[0])
        {
            l++;
            l=first[g][l];
            if(!l)break;
            g++;
        }
        if(a[n]!='*')
        {
            if(g!=gs[0]+1||l>r)continue;
            ans+=(last[r]==gs[gs[0]]);
        }
        else if(g==gs[0]+1&&l<=r)ans++;
    }
    cout<<ans<<endl;
    return 0;
}

完。