Contest - 2021-07-12 个人排位赛1

A Awkward Digits

题意

给你一个数n 的二进制表示和三进制表示,二进制表示和三进制表示中都有一个数错误,让你求原来的n是什么。
其中 0 < = n < = 1 e 9 0<=n<=1e9 0<=n<=1e9

Solution

暴力枚举二进制数中的某一位错误,三进制数中的某一位错误,将其修正后,看看二进制数和三进制数是否相等,若相等,转换为十进制得到答案。(这个方法需要较多的特判)
暴力枚举二进制数中的某一位错误,改正后转化为三进制,与原来的三进制数比较,看其是否只有一位不同,若是,转换为十进制即是答案。(更为简单的方法,特判少一点)

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
string s1,s2;
int n,m;
ll a[50],b[50];
ll x=0,y=0;
int main()
{
   
    cin>>s1>>s2;
    n=s1.length();
    m=s2.length();
    a[0]=b[0]=1;
    for(int i=1;i<=40;i++)
    {
   
        a[i]=1ll*a[i-1]*2;
        b[i]=1ll*b[i-1]*3;
    }
    for(int i=0;i<n;i++)x+=(s1[i]-'0')*a[n-1-i];
    for(int i=0;i<m;i++)y+=(s2[i]-'0')*b[m-1-i];
    for(int i=0;i<n;i++)
    {
   
        x-=(s1[i]-'0')*a[n-1-i];
        for(int j=0;j<m;j++)
        {
   
            y-=(s2[j]-'0')*b[m-1-j];
            if(s1[i]=='0')
            {
   
                if(s2[j]=='0')
                {
   
                    if(x+a[n-1-i]==y+b[m-1-j])
                    {
   
                        cout<<(x+a[n-1-i]);
                        return 0;
                    }
                    else if(x+a[n-1-i]==y+2*b[m-1-j])
                    {
   
                        cout<<(x+a[n-1-i]);
                        return 0;
                    }
                }
                else if(s2[j]=='1')
                {
   
                    if(x+a[n-1-i]==y)
                    {
   
                        cout<<(x+a[n-1-i]);
                        return 0;
                    }
                    else if(x+a[n-1-i]==y+2*b[m-1-j])
                    {
   
                        cout<<(x+a[n-1-i]);
                        return 0;
                    }
                }
                else
                {
   
                    if(x+a[n-1-i]==y+b[m-1-j])
                    {
   
                        cout<<(x+a[n-1-i]);
                        return 0;
                    }
                    else if(x+a[n-1-i]==y)
                    {
   
                        cout<<(x+a[n-1-i]);
                        return 0;
                    }
                }
            }
            else
            {
   
                if(s2[j]=='0')
                {
   
                    if(x==y+b[m-1-j])
                    {
   
                        cout<<(x);
                        return 0;
                    }
                    else if(x==y+2*b[m-1-j])
                    {
   
                        cout<<(x);
                        return 0;
                    }
                }
                else if(s2[j]=='1')
                {
   
                    if(x==y)
                    {
   
                        cout<<(x);
                        return 0;
                    }
                    else if(x==y+2*b[m-1-j])
                    {
   
                        cout<<(x);
                        return 0;
                    }
                }
                else
                {
   
                    if(x==y+b[m-1-j])
                    {
   
                        cout<<(x);
                        return 0;
                    }
                    else if(x==y)
                    {
   
                        cout<<(x);
                        return 0;
                    }
                }
            }
            y+=(s2[j]-'0')*b[m-1-j];
        }
        x+=(s1[i]-'0')*a[n-1-i];
    }
    return 0;
}

B Above the Median

题意

给定一个长度为n,一个数x,接下来给定长度为n的数组数组,求这个数组内,有多少个区间的中位数大于等于n。
中位数:假设区间长度为k,那么中位数就是区间内的数排序过后的第 ⌊ k + 1 2 ⌋ \lfloor \frac{k+1}{2} \rfloor 2k+1

Solutin

先预处理这个数组,将数组中小于x的数记为-1,大于等于x的数记为1,中位数大于x即区间内1的个数大于等于-1,即区间和大于等于0,设一个变量rela来记录0的相对位置,如果当前要加的值为1,说明将之前所有的区间和都加上1,即相对位置rela左移1位,再往rela右边一个位置加上1,如果当前要加的值为-1,说明之前所有和都减少1,即相对位置右移一位,再往rela左边一个位置加上1,然后通过树状数组查询有多少个值大于等于0的数。

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n,x;
int a[100005];
int tree[400005];
const int N=1e5+10;
int lowbit(int x){
   return x&(-x);}
void update(int x,int val)
{
   
    for(int i=x;i<=400000;i+=lowbit(i))tree[i]+=val;
}
int query(int x)
{
   
    int res=0;
    while(x)
    {
   
        res+=tree[x];
        x-=lowbit(x);
    }
    return res;
}
int main()
{
   
    scanf("%d%d",&n,&x);
    for(int i=1;i<=n;i++)
    {
   
        scanf("%d",&a[i]);
        if(a[i]>=x)a[i]=1;
        else a[i]=-1;
    }
    int rela=0;
    ll res=0;
    for(int i=1;i<=n;i++)
    {
   
        if(a[i]>0)rela--;
        else rela++;
        update(rela+a[i]+N,1);
        res+=query(400000)-query(rela+N-1);
    }
    printf("%lld",res);

    return 0;
}

C Moo Sick

题意

给了A和B两个序列,问A中有多少个长得向B的序列,并且输出长像的序列在A中的起始位置
长得像是指满足一下条件
1.区间长度与B的长度一致
2.整体加或减某个数后,经过重新排列能跟B完全一致

Soltion

暴力枚举区间,排序后判断差值是否一致

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n,m;
int a[20005];
int b[15],c[15];
vector<int>res;
int main()
{
   
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)scanf("%d",&b[i]);
    sort(b+1,b+1+m);
    for(int i=1;i<=n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            c[j+1]=a[i+j];
        }
        sort(c+1,c+1+m);
        int d=b[1]-c[1];
        bool flag= true;
        for(int j=2;j<=m;j++)
        {
   
            if(d!=b[j]-c[j])
            {
   
                flag=false;
                break;
            }
        }
        if(flag)res.push_back(i);
    }
    printf("%d\n",res.size());
    for(int i=0;i<res.size();i++)
        printf("%d\n",res[i]);
    return 0;
}

D Cow Lineup

题意

n头牛,给出这n头牛的位置和品种,找到最小的区间长度,满足这个区间内包含了所有品种的牛。

Solution

暴力枚举右端点,然后再枚举左端点,只要左端点所处位置的那个品种的牛出现两次及以上,就增大左端点大小,如果此时包含所有品种的牛,则更新答案,取最小值。

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n;
vector<P>e;
int a[50005];
int vis[50005];
int main()
{
   
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
   
        int x,y;scanf("%d%d",&x,&y);
        e.push_back(P(x,y));
        a[i]=y;
    }
    sort(e.begin(),e.end());
    sort(a,a+n);
    int k=unique(a,a+n)-a;
    for(int i=0;i<n;i++)
    {
   
        int qaq=lower_bound(a,a+k,e[i].second)-a;
        e[i].second=qaq;
    }
    int c=0;
    int res=INF;
    int l=0,r=0;
    while(r<n)
    {
   
        int id=e[r].second;
        if(vis[id]==0)c++;
        vis[id]++;
        while(l<n&&vis[e[l].second]>1)
        {
   
            vis[e[l].second]--;
            if(c==k)res=min(e[r].first-e[l].first,res);
            l++;
        }
        if(c==k)res=min(e[r].first-e[l].first,res);
        r++;
    }
    printf("%d",res);
    return 0;
}

E Cow Beauty Pageant I

题意

求两个X连通块之间的最短距离。

Solution

将其中一个连通块的距离标记为0,其余点标记为INF,从距离为0的点出发,跑一遍bfs,求最短距离即可

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n,m;
char tu[55][55];
int dx[]={
   0,0,1,-1},dy[]={
   1,-1,0,0};
queue<P>q;
int vis[55][55];
void bfs1(int x,int y)
{
   
    queue<P>qq;
    qq.push(P(x,y));
    tu[x][y]='.';
    vis[x][y]=1;
    while(!qq.empty())
    {
   
        P p=qq.front();qq.pop();
        q.push(p);
        for(int i=0;i<4;i++)
        {
   
            int x=dx[i]+p.first;
            int y=dy[i]+p.second;
            if(x<0||x>=n||y<0||y>=m)continue;
            if(vis[x][y]==1||tu[x][y]=='.')continue;
            tu[x][y]='.';
            vis[x][y]=1;
            qq.push(P(x,y));
        }
    }
}
int bfs2()
{
   
    int res=INF;
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            if(vis[i][j]==0)vis[i][j]=INF;
            else vis[i][j]=0;
        }
    }
    while(!q.empty())
    {
   
        P p =q.front();q.pop();
        if(tu[p.first][p.second]=='X')res=min(res,vis[p.first][p.second]);
        for(int i=0;i<4;i++)
        {
   
            int x=dx[i]+p.first;
            int y=dy[i]+p.second;
            if(x<0||x>=n||y<0||y>=m)continue;
            if(vis[x][y]<=vis[p.first][p.second]+1)continue;
            vis[x][y]=vis[p.first][p.second]+1;
            q.push(P(x,y));
        }

    }
    return res;
}
int main()
{
   
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)scanf("%s",tu[i]);
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            if(tu[i][j]=='X')
            {
   
                bfs1(i,j);
            }
            if(!q.empty())break;
        }
        if(!q.empty())break;
    }
    int res=bfs2();

    printf("%d",res-1);
    return 0;
}

F Contest Timing

题意

给出结束时间的day、hour、minute,求这个时间距离11号11:11过了多久,如果结束时间在此之前,输出-1,在这个时间之后,输出过了多少分钟才结束

Solution

将时间转换为分钟,然后比较大小,输出

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int d,h,m;
int main()
{
   
    cin>>d>>h>>m;
    ll x=(d-11)*24*60+(h-11)*60+m-11;
    if(x<0)cout<<-1;
    else cout<<x;
    return 0;
}

G Paint by Letters

H Cow Beauty Pageant II

题意

给定三个X的联通块,求三个联通块最少需要添加几个X才能相连通

Solution

将图中的每个点(这里指’.’)都作为起点,跑一遍bfs,得到的距离分别为d1,d2,d3,那么d1+d2+d3-2即为答案,最终答案为所有的结果最小值,然后三个联通块分别以每一个连通块最为起点,跑一遍bfs

代码
// 以每一个点(‘.’)跑一遍bfs,三个连通块之间分别跑一次bfs
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n,m;
char tu[505][505];
int dx[]={
   0,0,1,-1},dy[]={
   1,-1,0,0};
int d[10];
int vis[505][505];
int dd[505][505];
int res=INF;
void bfs(int x,int y,int id)
{
   
    queue<P>q;
    q.push(P(x,y));
    while(!q.empty())
    {
   
        P p=q.front();q.pop();
        tu[p.first][p.second]=(char)('0'+id);
        for(int i=0;i<4;i++)
        {
   
            x=dx[i]+p.first;
            y=dy[i]+p.second;
            if(x<0||x>=n||y<0||y>=m)continue;
            if(tu[x][y]!='X')continue;
            q.push(P(x,y));
            tu[x][y]=(char)('0'+id);
        }
    }
}
void bfs1(char ch)
{
   
    queue<P>q;
    memset(vis,INF,sizeof(vis));
    memset(dd,-1,sizeof(dd));
    memset(d,INF,sizeof(d));
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            if(tu[i][j]==ch)
            {
   
                q.push(P(i,j));
                vis[i][j]=0;
            }
        }
    }
    while(!q.empty())
    {
   
        P p = q.front(); q.pop();
        if(dd[p.first][p.second]==1)continue;
        dd[p.first][p.second]=1;
        char tem=tu[p.first][p.second];
        if((ch=='1'&&tem=='2')||(ch=='2'&&tem=='1'))
        {
   
            d[1]=min(vis[p.first][p.second],d[1]);
        }
        if((ch=='1'&&tem=='3')||(ch=='3'&&tem=='1'))
        {
   
            d[2]=min(vis[p.first][p.second],d[2]);
        }
        if((ch=='2'&&tem=='3')||(ch=='3'&&tem=='2'))
        {
   
            d[3]=min(vis[p.first][p.second],d[3]);
        }
        for(int i=0;i<4;i++)
        {
   
            int x=dx[i]+p.first;
            int y=dy[i]+p.second;
            if(x<0||x>=n||y<0||y>=m)continue;
            if(vis[p.first][p.second]+1>=vis[x][y])continue;
            q.push(P(x,y));
            vis[x][y]=vis[p.first][p.second]+1;
        }
    }
    sort(d+1,d+4);
    res=min(res,d[1]+d[2]-2);
}
void bfs2(int x,int y)
{
   
    queue<P>q;
    memset(vis,INF,sizeof(vis));
    memset(d,INF,sizeof(d));
    vis[x][y]=0;
    q.push(P(x,y));
    while(!q.empty())
    {
   
        P p=q.front();q.pop();
        if(tu[p.first][p.second]=='1')d[1]=min(d[1],vis[p.first][p.second]);
        if(tu[p.first][p.second]=='2')d[2]=min(d[2],vis[p.first][p.second]);
        if(tu[p.first][p.second]=='3')d[3]=min(d[3],vis[p.first][p.second]);
        for(int i=0;i<4;i++)
        {
   
            x=p.first+dx[i];
            y=p.second+dy[i];
            if(x<0||x>=n||y<0||y>=m)continue;
            if(vis[x][y]<=1+vis[p.first][p.second])continue;
            vis[x][y]=1+vis[p.first][p.second];
            q.push(P(x,y));
        }
    }
    res=min(d[1]+d[2]+d[3]-2,res);
}
int main()
{
   
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)scanf("%s",tu[i]);
    memset(d,INF,sizeof(d));
    int c=0;
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            if(tu[i][j]=='X')
            {
   
                ++c;
                bfs(i,j,c);
            }
        }
    }
    bfs1('1');
    bfs1('2');
    bfs1('3');
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            if(tu[i][j]=='.')
                bfs2(i,j);
        }
    }
    printf("%d",res);
    return 0;
}
/* 9 9 ......... .....X... ......... ........X ......... .....X... ......... ......... ......... */
// 以每个点('.','X')跑一遍bfs
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n,m;
char tu[505][505];
int dx[]={
   0,0,1,-1},dy[]={
   1,-1,0,0};
int d[10];
int vis[505][505];
int dd[505][505];
int res=INF;
void bfs(int x,int y,int id)
{
   
    queue<P>q;
    q.push(P(x,y));
    while(!q.empty())
    {
   
        P p=q.front();q.pop();
        tu[p.first][p.second]=(char)('0'+id);
        for(int i=0;i<4;i++)
        {
   
            x=dx[i]+p.first;
            y=dy[i]+p.second;
            if(x<0||x>=n||y<0||y>=m)continue;
            if(tu[x][y]!='X')continue;
            q.push(P(x,y));
            tu[x][y]=(char)('0'+id);
        }
    }
}
void bfs1(int x,int y)
{
   
    char ch=tu[x][y];
    queue<P>q;
    memset(vis,INF,sizeof(vis));
    memset(d,INF,sizeof(d));
    vis[x][y]=0;
    q.push(P(x,y));
    while(!q.empty())
    {
   
        P p=q.front();q.pop();
        if(tu[p.first][p.second]=='1')d[1]=min(d[1],vis[p.first][p.second]);
        if(tu[p.first][p.second]=='2')d[2]=min(d[2],vis[p.first][p.second]);
        if(tu[p.first][p.second]=='3')d[3]=min(d[3],vis[p.first][p.second]);
        for(int i=0;i<4;i++)
        {
   
            x=p.first+dx[i];
            y=p.second+dy[i];
            if(x<0||x>=n||y<0||y>=m)continue;
            if(vis[x][y]<=1+vis[p.first][p.second])continue;
            if(ch==tu[x][y]&&ch!='.')
                vis[x][y]=0;
            else
                vis[x][y]=1+vis[p.first][p.second];
            q.push(P(x,y));
        }
    }
    //cout<<d[1]<<' '<<d[2]<<' '<<d[3]<<endl;
    res=min(d[1]+d[2]+d[3]-2,res);
}
int main()
{
   
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)scanf("%s",tu[i]);
    memset(d,INF,sizeof(d));
    int c=0;
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            if(tu[i][j]=='X')
            {
   
                ++c;
                bfs(i,j,c);
            }
        }
    }
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            bfs1(i,j);
        }
    }
    printf("%d",res);
    return 0;
}
/* 9 9 ......... .....X... ......... ........X ......... .....X... ......... ......... ......... */

I Cow Steeplechase

题意

给定n条水平线或竖直线的端点坐标,求最多能得到多少条不相交的线段

solution

两条线段有交点,就将线段看作点,有交点即代表两个点之间有一条边,任意两个点之间的连边不会相交,也就是说明要跑二分图的最大权独立子集。最大权独立子集=点数-二分图最大匹配。

代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n;
vector<P>s,t;
vector<int>e[300];
int used[300];
int vis[300];
bool found(int x)
{
   
    for(int i=0;i<e[x].size();i++)
    {
   
        if(!used[e[x][i]])
        {
   
            used[e[x][i]]=1;
            if(vis[e[x][i]]==-1||found(vis[e[x][i]]))
            {
   
                vis[e[x][i]]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
   
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
   
        int x1,x2,y1,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        if(x1>x2)swap(x1,x2);
        if(y1>y2)swap(y1,y2);
        s.push_back(P(x1,y1));
        t.push_back(P(x2,y2));
    }
    for(int i=0;i<n;i++)
    {
   
        if(s[i].second!=t[i].second)continue;
        for(int j=0;j<n;j++)
        {
   
            if(s[j].first!=t[j].first)continue;
            if(s[i].second>=s[j].second&&s[i].second<=t[j].second&&s[i].first<=s[j].first&&t[i].first>=s[j].first)e[i].push_back(j);
        }
    }
    int sum=0;
    memset(vis,-1,sizeof(vis));
    for(int i=0;i<n;i++)
    {
   
        memset(used,0,sizeof(used));
        if(e[i].size()>0)
        {
   
            if(found(i))sum++;
        }
    }

    printf("%d",n-sum);
    return 0;
}

J Sum of Distances

K Tile Exchanging

L Binary Sudoku