CF6

半腔热情 提交于 2020-02-01 22:36:44

A

A

不解释

#include<bits/stdc++.h>
using namespace std;
namespace red{
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    int a[5];
    inline bool check(int id)
    {
        return (a[id]+a[id+1]>a[id+2]&&a[id+2]-a[id+1]<a[id]);
    }
    inline bool check2(int id)
    {
        return (a[id]+a[id+1]>=a[id+2]);
    }
    inline void main()
    {
        for(int i=1;i<=4;++i) a[i]=read();
        sort(a+1,a+4+1);
        if(check(1)||check(2)) puts("TRIANGLE");
        else if(check2(1)||check2(2)) puts("SEGMENT");
        else puts("IMPOSSIBLE");
    }
}
signed main()
{
    red::main();
    return 0;
}

B

B

找到位置开始\(dfs\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    int n,m,sum;
    char ch;
    char mp[110][110];
    bool vis[1010];
    bool g[110][110];
    int dx[]={0,-1,1,0,0},dy[]={0,0,0,1,-1};
    inline void dfs(int x,int y)
    {
        for(int i=1;i<=4;++i)
        {
            int tx=x+dx[i],ty=y+dy[i];
            if(tx<1||tx>n||ty<1||ty>m) continue;
            if(g[tx][ty]) continue;
            g[tx][ty]=1;
            if(mp[tx][ty]==ch) dfs(tx,ty);
            else if(mp[tx][ty]!='.'&&!vis[mp[tx][ty]])
            {
                vis[mp[tx][ty]]=1;
                ++sum;
            }
        }
    }
    inline void main()
    {
        n=read(),m=read();
        for(ch=getchar();(ch<'A'||ch>'Z');ch=getchar());
        for(int i=1;i<=n;++i)
        {
            scanf("%s",mp[i]+1);
        }
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=m;++j)
            {
                if(mp[i][j]==ch)
                {
                    dfs(i,j);
                    printf("%d\n",sum);
                    return;
                }
            }
        }
    }
}
signed main()
{
    red::main();
    return 0;
}

C

C

也就一个模拟,前后维护两个指针

#include<bits/stdc++.h>
using namespace std;
namespace red{
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=1e5+10;
    int n;
    int a[N];
    int t1,t2,sum1,sum2;
    inline void main()
    {
        n=read();
        for(int i=1;i<=n;++i)
        {
            a[i]=read();
        }
        t1=0,t2=n+1;
        while(t1<t2-1)
        {
            ++t1;
            sum1+=a[t1];
            while(sum2<sum1&&t1<t2-1) --t2,sum2+=a[t2];
        }
        cout<<t1<<' '<<n-t1<<endl;
    }
}
signed main()
{
    red::main();
    return 0;
}

D

D

看了眼数据范围:

\(3\le n\le 10\) , \(1\le b < a\le 10\) , \(1\le h_i \le 15\)

\(!\)

搜他丫的

注意两边是没法点火球的,先把两边消掉,然后在中间迭代加深

因为\(n=3\)的时候预处理两边会出锅,先判掉

然后提交

\(TLE\)

发现一个性质:火球先后顺序无关

减少一下搜索重复状态:只在一个火球之后扔火球

\(AC\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=110;
    int n,a,b;
    int hp[N];
    int bp[N],c[N];
    int d[N],ans[N];
    int t,sum;
    inline bool dfs(int pre,int now,int up)
    {
        if(now>up)
        {
            for(int i=1;i<=t;++i)
                if(~bp[i]) return 0;
            return 1;
        }
        for(int i=pre;i<=t;++i)
        {
            int q1=bp[i-1],q2=bp[i],q3=bp[i+1];
            bp[i-1]=max(bp[i-1]-b,-1);
            bp[i]=max(bp[i]-a,-1);
            bp[i+1]=max(bp[i+1]-b,-1);
            ans[now]=c[i];
            if(dfs(i,now+1,up)) return 1;
            bp[i-1]=q1,bp[i]=q2,bp[i+1]=q3;
        }
        return 0;
    }
    inline void solve()
    {
        sum=max(max(hp[1]/b+1,hp[3]/b+1),hp[2]/a+1);
        printf("%d\n",sum);
        for(int i=1;i<=sum;++i) printf("%d ",2);
        exit(0);
    }
    inline void main()
    {
        n=read(),a=read(),b=read();
        for(int i=1;i<=n;++i) hp[i]=read();
        if(n==3) solve();
        t=(hp[1])/b+1;
        hp[1]=-1;
        hp[2]=max(hp[2]-t*a,-1);
        hp[3]=max(hp[3]-t*b,-1);
        for(int i=1;i<=t;++i) d[i]=2;
        sum+=t;
        t=(hp[n])/b+1;
        hp[n]=-1;
        hp[n-1]=max(hp[n-1]-t*a,-1);
        hp[n-2]=max(hp[n-2]-t*b,-1);
        for(int i=sum+1;i<=sum+t;++i) d[i]=n-1;
        sum+=t;
        bool flag=0;
        for(int i=1;i<=n;++i)
            if(~hp[i]) flag=1;
        if(!flag)
        {
            printf("%d\n",sum);
            for(int i=1;i<=sum;++i) printf("%d ",d[i]);
            return;
        }
        for(int i=1;;++i)
        {
            t=0;
            for(int j=2;j<n;++j) bp[++t]=hp[j],c[t]=j;
            if(dfs(1,1,i))
            {
                for(int j=sum+1;j<=sum+i;++j) d[j]=ans[j-sum];
                sum+=i;
                sort(d+1,d+sum+1);
                printf("%d\n",sum);
                for(int j=1;j<=sum;++j) printf("%d ",d[j]);
                return;
            }
        }
    }
}
signed main()
{
    red::main();
    return 0;
}

然后发现这题目是可以\(dp\)的……

\(dp[i][j][k]\)表示前\(i\)个都死了,第\(i\)个用了\(j\)个火球,第\(i+1\)个用了\(k\)个火球的最小代价

不得不说这个状态很巧妙……

然后暴力转移\(n*h^3\),其中\(h=max\{h_i\}\)

其中我们发现当枚举了当前状态之后,之前那个转移状态可以后缀最大值优化,优化到\(n*h^2\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=110;
    int n,a,b,ret,t0,t1,t2;
    int hp[N];
    int f[21][21][21],g[21][21][21];
    inline void main()
    {
        n=read(),a=read(),b=read();
        for(int i=1;i<=n;++i) hp[i]=read();
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=20;++i)
            if(i*b>hp[1]) f[1][0][i]=0;
        //kcz:i-n死完了,i-1用j个,i用k个
        //俺:1-i死完了,i用j个,i用k+1个 
        //dp方法:直接dp,最后输出满足要求的状态
        for(int i=1;i<=n;++i)
        {
            if(i>1)
            {
                for(int k=0;k<=16;++k)
                {
                    int tmp=hp[i]-k*b;
                    for(int j=0;j<=16;++j)
                    {
                        f[i][j][k]=j+g[i-1][tmp<0?0:tmp/b+1][j];
                        tmp-=a;
                    }
                }
            }
            for(int k=0;k<=16;++k)
            {
                g[i][16][k]=f[i][16][k];
                for(int j=15;~j;--j)
                    g[i][j][k]=min(g[i][j+1][k],f[i][j][k]);
            }
        }
        int i=n,j=0,k=0;
        printf("%d\n",f[i][j][k]);
        while(--i>1)
        {
            int tmp=hp[i+1]-j*a-k*b;
            int l=tmp<0?0:tmp/b+1;
            while(f[i][l][j]!=f[i+1][j][k]-j) ++l;
            k=j,j=l;
            for(int u=1;u<=l;++u) printf("%d ",i);
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*
9 3 1
1 5 2 4 6 2 3 4 2

*/

E

E

预处理\(st\)

二分求答案

然后统计答案

#include<bits/stdc++.h>
using namespace std;
namespace red{
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=1e5+10;
    int n,m,l,r,mid,ret,sum;
    int a[N],lg[N];
    bool s[N];
    int f[N][21],g[N][21];
    inline int get_max(int l,int r)
    {
        int k=lg[r-l+1]-1;
        return max(f[l][k],f[r-(1<<k)+1][k]);
    }
    inline int get_min(int l,int r)
    {
        int k=lg[r-l+1]-1;
        return min(g[l][k],g[r-(1<<k)+1][k]);
    }
    inline bool check(int x)
    {
        for(int l=1;l<=n;++l)
        {   
            int r=l+x-1;
            if(r>n) return 0;
            if(get_max(l,r)-get_min(l,r)<=m) return 1;
        }
        return 0;
    }
    inline void get_sum(int x)
    {
        for(int l=1;l<=n;++l)
        {
            int r=l+x-1;
            if(r>n) return;
            if(get_max(l,r)-get_min(l,r)<=m) ++sum,s[l]=1;
        }
    }
    inline void main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;++i) a[i]=f[i][0]=g[i][0]=read();
        for(int i=1;i<=n;++i) lg[i]=lg[i>>1]+1;
        lg[0]=1;
        for(int i=1;i<=20;++i)
        {
            for(int j=1;j+(1<<i)-1<=n;++j)
            {
                f[j][i]=max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
                g[j][i]=min(g[j][i-1],g[j+(1<<(i-1))][i-1]);
            }
        }
        l=1,r=n;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid)) ret=mid,l=mid+1;
            else r=mid-1;
        }
        get_sum(ret);
        printf("%d %d\n",ret,sum);
        for(int i=1;i<=n;++i)
        {
            if(s[i]) printf("%d %d\n",i,i+ret-1);
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!