Codeforces Round #662 (Div. 2)

就写了两个题,以为要掉分,结果早上起来发现还上分了(说明wtcl

A - Rainbow Dash, Fluttershy and Chess Coloring

无论边长是奇数还是偶数,考虑每次操作最外层的一圈,一个人操作一圈的一般,然后另一个人就能够把这一圈涂满,而且还能继续操作最外圈。每次2人操作后问题变成边长-2的情况。稍微思考一下就可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int main()
{
    IO;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        if(n&1)
            cout<<(n-3)/2+2<<endl;
        else
            cout<<(n-2)/2+2<<endl;
    }
    return 0;
}

B - Applejack and Storages

统计4的倍数和2的倍数。其中既是4的倍速也是2的倍数只看做4的倍数。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int mp[N];
int n,q;
int main()
{
    IO;
    cin>>n;
    int x=0,y=0;
    for(int i=1;i<=n;i++)
    {
        int a;
        cin>>a;
        mp[a]++;
        if(mp[a]%2==0) y++;//加完后是2的倍数
        if(mp[a]%4==0) x++,y-=2; //加完后是4的倍数(要把二的倍数减去)
    }
    cin>>q;
    while(q--)
    {
        char op;
        int a;
        cin>>op>>a;
        if(op=='+')
        {
            mp[a]++;
            if(mp[a]%2==0) y++;
            if(mp[a]%4==0) x++,y-=2;
        }
        else
        {
            if(mp[a]%2==0) y--;//减之前是2的倍数 2的倍数减小一个
            if(mp[a]%4==0) x--,y+=2;//减之前是4的倍数 4的倍数减小一个,2的倍数最终应该增加一个(由于上面减了一个要加二个这点wa了2发)
            mp[a]--;
        }
        if(x>=1&&y>=2||x>=2) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

C - Pinkie Pie Eats Patty-cakes

最小距离最大?二分?,做题的时候我就发现二分的check函数好像不容易写。如果能够写出check函数其实好像不用二分直接答案就出来了。
果不其然,群友说这就是个贪心题,后来想了想果然是。1111222233334445566789
比如上述序列,构造方式如下:
1234569
123457
123468
123
如果是11111222233334445566789
123469
12346
12357
12458
13
因此有以下贪心

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100010;
int mp[N],n;
int main()
{
    IO;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        int mx=0;
        memset(mp,0,sizeof mp);
        for(int i=1;i<=n;i++)
        {
            int a;
            cin>>a;
            mp[a]++;
            mx=max(mx,mp[a]);
        }
        int cnt=0;
        for(int i=0;i<N;i++)
            if(mp[i]==mx) cnt++;
        cout<<cnt+(n-cnt*mx)/(mx-1)-1<<endl;
    }
    return 0;
}

D-Rarity and New Dress

悬线dp?第一次听说,一定要把这题补了
解法一:二分抄代码题解
维护菱形中间点,先求上下最长,维护左右最长(不能超过上下最长)

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#define debug(x) cout<<#x<<": "<<x<<" "
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2010;
int n,m;
ll ans;
int u[N][N],d[N][N],l[N][N],r[N][N];
int h[N][N];
char s[N][N];
int main()
{
    IO;
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>s[i]+1;
    // 预处理
    for(int j=1;j<=m;j++)
    {
        for(int i=1;i<=n;i++)
        {
            if(s[i][j]==s[i-1][j]) u[i][j]=u[i-1][j]+1;
            else u[i][j]=1;
        }
        for(int i=n;i;i--)
        {
            if(s[i][j]==s[i+1][j]) d[i][j]=d[i+1][j]+1;
            else d[i][j]=1;
        }
        for(int i=1;i<=n;i++) h[i][j]=min(d[i][j],u[i][j]);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(s[i][j]==s[i][j-1]) l[i][j]=min(l[i][j-1]+1,h[i][j]);
            else l[i][j]=1;
        }
        for(int j=m;j;j--)
        {
            if(s[i][j]==s[i][j+1]) r[i][j]=min(r[i][j+1]+1,h[i][j]);
            else r[i][j]=1;
        }
    }
    // 求答案
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ans+=min(l[i][j],r[i][j]);
    cout<<ans<<endl;
    return 0;
}

解法二:
这个菱形可以看成4个等腰直角三角形,维护等腰直角三角形(即菱形中心点)
f[i][j]表示s[i][j]为直角顶点最大等腰直角三角形。4次dp

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#define debug(x) cout<<#x<<": "<<x<<" "
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2010;
int n,m;
ll ans;
int f1[N][N],f2[N][N],f3[N][N],f4[N][N];
char s[N][N];
int main()
{
    IO;
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>s[i]+1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f1[i][j]=1;
            if(s[i][j]==s[i-1][j]&&s[i][j]==s[i][j-1]) f1[i][j]=min(f1[i-1][j],f1[i][j-1])+1;
        }
    for(int i=1;i<=n;i++)
        for(int j=m;j;j--)
        {
            f2[i][j]=1;
            if(s[i][j]==s[i-1][j]&&s[i][j]==s[i][j+1]) f2[i][j]=min(f2[i-1][j],f2[i][j+1])+1;
        }
    for(int i=n;i;i--)
        for(int j=1;j<=m;j++)
        {
            f3[i][j]=1;
            if(s[i][j]==s[i+1][j]&&s[i][j]==s[i][j-1]) f3[i][j]=min(f3[i+1][j],f3[i][j-1])+1;
        }
    for(int i=n;i;i--)
        for(int j=m;j;j--)
        {
            f4[i][j]=1;
            if(s[i][j]==s[i+1][j]&&s[i][j]==s[i][j+1]) f4[i][j]=min(f4[i+1][j],f4[i][j+1])+1;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) 
            ans+=min(min(f1[i][j],f2[i][j]),min(f3[i][j],f4[i][j]));
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/107875680