总之就是 | CF 1534 ABC 题解

前言

我是大傻逼!!!!!!!!!!!!!!

大概就是做题的时候 ABC 都想出来了,如何疯狂 TLE On PreTest 2 。

后来 A 题改出来了, B 和 C 到最后都没弄好。

搞得我比赛完 2:35 ,直到三点半都睡不着。

A Colour the Flag

CF1534A Colour the Flag

题意简述

给你一个方阵,方阵由 "W" "R" "." 这三种字符组成,其中 "." 代表的是空位置,可以任意的填放剩下两种字符。

现在问你当前给出的方阵能否填充为一个 "WR相间" 的方阵,

若可行,输出 "YES" 并输出这个符合要求的方阵;

否则输出 "NO" 。

每个测试点有多组数据。

思路简述

可以发现实际上能够满足要求的方阵只有两种,即左上角是 W左上角是 R 两种。

于是我们可以预处理一下然后进行比较即可。

Code

赛时代码,略丑勿喷。

#include <bits/stdc++.h>
#define Heriko return
#define Deltana 0
#define S signed
#define LL long long
#define R register
#define I inline
#define CI const int
#define mst(a, b) memset(a, b, sizeof(a))
#define ON std::ios::sync_with_stdio(false)
using namespace std;
I void fr(LL & x)
{
    LL f=1;
    char c=getchar();
    x=0;
    while(c<'0' or c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while (c>='0' and c<='9') 
    {
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    x*=f;
}
I void fw(LL x)
{
    if(x<0) putchar('-'),x=-x;
    static LL stak[35];
    LL top=0;
    do
    {
        stak[top++]=x%10;
        x/=10;
    }
    while(x);
    while(top) putchar(stak[--top]+'0');
}
char ch[100][100];
LL t,n,m,a[100][100],b[100][100],c[100][100];
I void cw()
{
    mst(b,0);mst(c,0);
    for(R LL i=1;i<=100;++i)
        for(R LL j=1;j<=100;++j)
            if((i+j)&1) b[i][j]=1,c[i][j]=2;
            else b[i][j]=2,c[i][j]=1;
}
S main()
{
    fr(t);
    cw();
    while(t--)
    {
        fr(n),fr(m);
        mst(a,0);
        for(R LL i=1;i<=n;++i)
            for(R LL j=1;j<=m;++j)
                cin>>ch[i][j];
        for(R LL i=1;i<=n;++i)
            for(R LL j=1;j<=m;++j)
                if(ch[i][j]=='W') a[i][j]=1;
                else if(ch[i][j]=='R') a[i][j]=2;
        bool c1,c2;
        c1=c2=true;
        for(R LL i=1;i<=n;++i)
            for(R LL j=1;j<=m;++j)
                if(b[i][j]!=a[i][j] and a[i][j])
                {
                    c1=false;
                    break;
                }
        if(c1)
        {
            puts("YES");
            for(R LL i=1;i<=n;putchar('\n'),++i)
                for(R LL j=1;j<=m;++j)
                    if(b[i][j]==2) putchar('R');
                    else putchar('W');
            continue;
        }
        for(R LL i=1;i<=n;++i)
            for(R LL j=1;j<=m;++j)
                if(c[i][j]!=a[i][j] and a[i][j])
                {
                    c2=false;
                    break;
                }
        if(c2)
        {
            puts("YES");
            for(R LL i=1;i<=n;putchar('\n'),++i)
                for(R LL j=1;j<=m;++j)
                    if(c[i][j]==2) putchar('R');
                    else putchar('W');
            continue;
        }
        else
        {
            puts("NO");
            continue;
        }   
    }
    Heriko Deltana;
}

B Histogram Ugliness

CF1534B Histogram Ugliness

题意简述

现有一个直方图,定义这个直方图的丑值为对它进行操作的次数 + 左右边缘长度(即图上红色线条),

可以对它进行的操作为:让其中一列的高度减一。

现在问你对于这个直方图,它能达到的最小的丑值

每个测试点有多组数据,

对于每个直方图的输入:

第一行,总列数 \(n\)

第二行,每一列的高度 \(a_i\)

思路简述

这个题唯一的减少丑值的途径就是对这个直方图进行操作,于是我们从这里入手。

可以发现,对于某一列,若它的高度 \(a_i\) 满足 \(a_i > a_{i-1}\ \&\ a_i > a_{i+1}\) ,那么对这一列进行操作就能减少 1 丑值。

换句话说,对这种“独峰”操作一次,能够减去两个单位的边缘长度,增加了一次操作,故总的来说丑值减一。

然后我们来看同时对相邻且与其他列相互孤立的两列进行操作的情况,

也就是 \(a_i = a_{i+1}\ \&\ a_i > a_{i-1}\ \&\ a_{i+1} > a_{i+2}\) 时,

可以发现这种情况下减去了两个单位的长度,但是操作次数也是加上了两次,所以这种操作不会对丑值减少造成贡献。

至于一次操作更多的情况,显然操作次数已经超过了减去的边缘长度,没有做这种操作的必要了。

简单总结一下就是,对“孤峰”操作可以帮助我们减去 1 丑值,

对“双峰”操作对我们达到最小丑值的目标毫无贡献,

而对“平原”的操作会让我们离达到最小丑值目标越来越远。

于是我们只需要考虑对“孤峰”进行操作。

在输入的时候先算出原始丑值,即最初的边缘长度,然后对“孤峰”进行判断即可。

Code

#include <bits/stdc++.h>
#define Heriko return
#define Deltana 0
#define S signed
#define LL long long
#define R register
#define I inline
#define CI const int
#define mst(a, b) memset(a, b, sizeof(a))
#define ON std::ios::sync_with_stdio(false)
using namespace std;
I void fr(LL & x)
{
    LL f=1;
    char c=getchar();
    x=0;
    while(c<'0' or c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while (c>='0' and c<='9') 
    {
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    x*=f;
}
I void fw(LL x)
{
    if(x<0) putchar('-'),x=-x;
    static LL stak[35];
    LL top=0;
    do
    {
        stak[top++]=x%10;
        x/=10;
    }
    while(x);
    while(top) putchar(stak[--top]+'0');
    putchar('\n');
}
CI MXX=5e5+5;
LL t,n,a[MXX],ans;
S main()
{
    fr(t);
    while(t--)
    {
        fr(n);ans=0;a[n+1]=a[0]=0;
        for(R LL i=1;i<=n;++i) fr(a[i]),ans+=abs(a[i]-a[i-1]);
        ans+=a[n];
        for(R LL i=1;i<=n;++i)
        {
            if(a[i]>a[i-1] and a[i]>a[i+1])
            {
                LL mid=max(a[i+1],a[i-1]);
                ans-=(a[i]-mid);
                a[i]=mid;
            }
        }
        fw(ans);
    }
    Heriko Deltana;
}

C Little Alawn's Puzzle

CF1534C Little Alawn's Puzzle

题意简述

题目给出一个 \(2 \times n\) 的数阵,问你在经过操作之后,能够满足没有相同数字在同一行的数阵能有多少个。

你可以进行的操作就是交换一列中的两个数字

由于答案可能会很大,所以你需要在输出之前模上 \(10^9+7\) ,并且每个测试点有多组数据。

思路简述

我们可以先来观察一下样例。

可以发现假如我们交换任意一列的两个数,其它的所有的拥有这两个数之一的列都也都应该被操作,否则将出现矛盾。

于是可以发现,其实每一组相关联的列都构成了一个环,于是我们可以建图来查环。

由于我脑袋比较直就随手写了个并查集,最后查一下有几个集即可。

Code

由于并查集 + 我的马蜂,您会在主函数中看到一列整齐划一的 for 。

#include <bits/stdc++.h>
#define Heriko return
#define Deltana 0
#define S signed
#define LL long long
#define R register
#define I inline
#define CI const int
#define mst(a, b) memset(a, b, sizeof(a))
#define ON std::ios::sync_with_stdio(false)
using namespace std;
I void fr(LL & x)
{
    LL f=1;
    char c=getchar();
    x=0;
    while(c<'0' or c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while (c>='0' and c<='9') 
    {
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    x*=f;
}
I void fw(LL x)
{
    if(x<0) putchar('-'),x=-x;
    static LL stak[35];
    LL top=0;
    do
    {
        stak[top++]=x%10;
        x/=10;
    }
    while(x);
    while(top) putchar(stak[--top]+'0');
    putchar('\n');
}
CI MXX=2e6+5,mod=1e9+7;
LL t,n,f[MXX],a1[MXX],ans,os[MXX];
LL find(LL x)
{
    if(x!=f[x]) f[x]=find(f[x]);
    Heriko f[x];
}
I void uni(LL a,LL b)
{
    f[find(a)]=find(b);
}
I LL powermod(LL a,LL n,LL m)
{
	if(n==0) Heriko 1%m;
	LL x=powermod(a,n/2,m);
	LL res=x*x%m;
	if(n%2!=0) res=res*a%m;
	Heriko res;
}
S main()
{
    fr(t);
    while(t--)
    {
        fr(n);f[n+n+1]=ans=0;
        for(R LL i=1;i<=n+n;++i) f[i]=i;
        for(R LL i=1;i<=n+n;++i) fr(a1[i]);
        for(R LL i=1;i<=n;++i) uni(a1[i],a1[i+n]);
        for(R LL i=1;i<=n+n;++i) os[i]=0;
        for(R LL i=1;i<=n+n;++i) os[find(i)]++;
        for(R LL i=1;i<=n;++i) if(os[i]) ans++;
        fw(powermod(2,ans,mod));
    }
    Heriko Deltana;
}

End

总的来说,我是 SB 。

我™码力就是屑!!!1

posted @ 2021-06-14 20:24  HerikoDeltana  阅读(118)  评论(1编辑  收藏  举报