上古退役选手康复训练1——CSP2020J-2

你没看错,一个前NOI Ag选手来做普及组了,马上打ICPC了我也准备练习一些。

连PJ都不会了,得分:100+100+30+100=330,甚至比初三还菜,nowcoder数据,思路也应该是这个分。

写一发题解吧(T3就写30分的)

T1

奇数直接输出-1,偶数按二进制位拆分

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
    cin>>n;
    if(n%2==1)cout<<-1;
    else for(int i=(1<<30);i>=2;i>>=1)
    if(i<=n)n=n-i,cout<<i<<' ';
}

T2

用个筒存一下每个分数上有多少人,每次加人的时候从大到小搜索一遍即可

#include<bits/stdc++.h>
using namespace std;
int n,w,a[601];
int main()
{
    scanf("%d%d",&n,&w);
    for(int i=1,x;i<=n;i++)
    {
        scanf("%d",&x),a[x]++;
        int t=max(1,i*w/100);
        for(int j=600;j>=0;j--)
        if(a[j]>=t){printf("%d ",j);break;}else t-=a[j];
    }
}

T3

不会做,只会暴力,就是开一个栈,每次遇到 | 或 & 弹出栈顶两个元素运算,遇到 ! 弹出栈顶一个元素运算,裸暴力复杂度O(n^2)。看上去像是一个动态DP,但我早就不会写那个玩意了。

#include<bits/stdc++.h>
using namespace std;
int n,m,tp,sz,a[100007],st[100007];
string s;
int main()
{
    getline(cin,s);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    scanf("%d",&m);
    sz=s.size();
    while(m--)
    {
        int i=0,x,t,t1,t2;
        scanf("%d",&x),a[x]^=1;
        tp=0;
        while(i<sz)
        {
            while(i<sz&&s[i]==' ')i++;
            if(s[i]=='x')
            {
                t=0,i++;
                while(i<sz&&s[i]>='0'&&s[i]<='9')t=t*10+s[i++]-'0';
                st[++tp]=a[t];
            }
            if(s[i]=='!')st[tp]^=1,i++;
            if(s[i]=='&')t1=st[tp--],t2=st[tp--],st[++tp]=(t1&t2),i++;
            if(s[i]=='|')t1=st[tp--],t2=st[tp--],st[++tp]=(t1|t2),i++;
            while(s[i]==' ')i++;
        }
        printf("%d\n",st[tp]),a[x]^=1;
    }
}

T4

70分做法很容易想到f[i][j]表示走到第j列,在第i行准备转弯的最大值,于是枚举上一行准备转弯的地方,对矩阵每一列做前缀和即可。

100分做法实际上是70分的优化,其实不需要枚举最后一次,直接f[i][j][0/1]表示在i,j往上/下走,从上一个方向推过来就行了,注意细节。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
ll a[1005][1005],f[1005][1005][2];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%lld",&a[i][j]);
    for(int i=1;i<=n;i++)f[i][0][0]=f[i][0][1]=-1e18;
    for(int j=1;j<=m;++j)
    {
        if(j==1)f[1][1][0]=a[1][1];else f[1][j][0]=max(f[1][j-1][0],f[1][j-1][1])+a[1][j];
        for(int i=2;i<=n;i++)
        f[i][j][0]=max(f[i-1][j][0],max(f[i][j-1][0],f[i][j-1][1]))+a[i][j];
        if(j==1)
        {
            f[1][1][1]=a[1][1];
            for(int i=2;i<=n;i++)f[i][j][1]=-1e18;
            continue;
        }
        f[n][j][1]=max(f[n][j-1][0],f[n][j-1][1])+a[n][j];
        for(int i=n-1;i;i--)
        f[i][j][1]=max(f[i+1][j][1],max(f[i][j-1][0],f[i][j-1][1]))+a[i][j];
    }
    printf("%lld",max(f[n][m][0],f[n][m][1]));
}

 

posted @ 2020-11-10 15:44  hfctf0210  阅读(155)  评论(0编辑  收藏  举报