Codeforces Round #771 (Div. 2)思路分享

Codeforces Round #771 (Div. 2)

B题最后被hack了.....不过最后还是加了17。。。不掉就行,下场要上粉!!!

A. Reverse

题目要求最小的字典序序列,比较显然的想法就是第一个元素找1,第二个元素找2....依次类推。

点击查看代码
#include<bits/stdc++.h>
#define ll long  long
#define db double 
using namespace std;
int n,T,a[510],b[510]; 
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<=n;++i)
        {
            if(i!=a[i])
            {
                int o;
                for(int j=i+1;j<=n;++j)
                {
                    if(i==a[j])
                    {
                        o=j;
                        break;
                    }
                }
                for(int j=i;j<=o;++j) b[j]=a[i+o-j];
                for(int j=i;j<=o;++j) a[j]=b[j];
                break;
            }
        }
        for(int i=1;i<=n;++i) printf("%d ",a[i]);
        puts("");
    }
    return 0;
} 

B. Odd Swap Sort

比赛的时候就被这个题卡了许久,到最后还是打了个\(O(n^2)\)的复杂度上去,数据1e5,我......脑子抽抽了估计...
发现只奇偶的才能换,也就是说相同的奇偶性是不能交换的,换句话说也就是相同奇偶性的数他们的相对位置是不变的。那么我们只需要分别对于奇数和偶数观察他们是否是有序的即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int T,n;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        bool flag=true;
        int l=0,r=0;
        for(int i=1;i<=n;++i)
        {
            int x;scanf("%d",&x);
            if(x%2==1&&x<l) flag=false;
            if(x%2==0&&x<r) flag=false;
            (x%2)?l=x:r=x; 
        }
        if(flag) puts("YES");
        else puts("NO");
    }
    return 0;
} 

C. Inversion Graph

C题一眼看过去就是知道是优化连边的题,对于逆序对,我的第一想法就是用树状数组求逆序对的方法。就是倒序,然后按权值大小,累计,每一个x,1 - x-1内的个数就是它对应的逆序数的个数。那么在这个题中就是x要与1 - x-1内的所有数连边。暴力的连边不可行,我们考虑怎么优化,我们最终的目的是让1 - x-1与x形成一个连通块,那么我们可以保留最小的那个数,将其他数都删去,这样,能连上这个连通块的其他的数时,一定也能连上这个连通块内的最小的数字。

点击查看代码
#include<bits/stdc++.h>
#define ll long  long
#define db double 
using namespace std;
const int N=1e5+10;
int n,T,a[N],f[N],vis[N],b[N],num;
priority_queue<int>q;
inline int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<=n;++i) f[i]=i,vis[i]=0;
        while(q.size()) q.pop();
        for(int i=n;i>=1;--i)
        {
            num=0;
            while(q.size()&&(-q.top())<a[i])
            {
                b[++num]=-q.top();
                q.pop();
            }
            if(num)
            {
                for(int j=2;j<=num;++j) f[b[j]]=b[1];
                f[a[i]]=b[1];
                q.push(-b[1]);
            }
            else q.push(-a[i]);
        }
        int cnt=0;
        for(int i=1;i<=n;++i) 
        {
            int t=getf(i);
            if(vis[t]) continue;
            vis[t]=1;cnt++;
        }
        printf("%d\n",cnt);
    }
    return 0;
} 

这个题当然也有其他的方法,我是采用优先队列去模拟这个过程。其实我们完全可以用单调栈去模拟这个过程,我们维护一个栈底到栈顶单调递增的栈,一旦出现一个元素将其他元素顶出栈时,我们考虑保留当中最大的元素,将所有的元素与最大的元素连边即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int T,n,a[N],st[N],top,f[N],vis[N];
inline int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]),f[i]=i,vis[i]=0;
        top=0;
        for(int i=1;i<=n;++i)
        {
            int ts=a[i];
            while(top&&a[i]<st[top])
            {
                ts=max(ts,st[top]);
                f[st[top]]=ts;
                top--;
            }
            f[a[i]]=ts;
            st[++top]=ts;
        }
        int cnt=0;
        for(int i=1;i<=n;++i)
        {
            int t=getf(i);
            if(vis[t]) continue;
            vis[t]=1;
            cnt++;
        }
        printf("%d\n",cnt);
    }
    return 0;
} 

D. Big Brush

这个题算是最后逆风翻盘了吧...记得之前在洛谷做过一个类似的题,这种覆盖性问题的解法就是倒着解....我们先找最后一个四个一起的小矩形,之后这些小矩形可以变成任意颜色,一直扩展即可。

#include #define ll long long #define db double using namespace std; const int N=1010; int n,m,c[N][N],num; queue<pair<int,int> >q; struct wy{int x,y,c;}b[N*N]; inline bool check(int x,int y) { if(x>=1&&x<n&&y>=1&&y<m) {="" int="" mx="max(max(c[x][y],c[x][y+1]),max(c[x+1][y],c[x+1][y+1]));" if(!mx)="" return="" false;="" if(c[x][y]&&c[x][y]!="mx)" if(c[x][y+1]&&c[x][y+1]!="mx)" if(c[x+1][y]&&c[x+1][y]!="mx)" if(c[x+1][y+1]&&c[x+1][y+1]!="mx)" true;="" }="" inline="" void="" clear(int="" x,int="" y)="" c[x][y]="c[x][y+1]=0;" c[x+1][y]="c[x+1][y+1]=0;" bool="" duan()="" for(int="" i="1;i<=n;++i)" j="1;j<=m;++j)" if(c[i][j])="" main()="" freopen("1.in","r",stdin);="" scanf("%d%d",&n,&m);="" scanf("%d",&c[i][j]);="" if(check(i,j))="" q.push({i,j});="" while(q.size())="" x="q.front().first,y=q.front().second;" q.pop();="" if(check(x,y))="" b[++num].x="x;" b[num].y="y;" b[num].c="max(max(c[x][y],c[x][y+1]),max(c[x+1][y],c[x+1][y+1]));" clear(x,y);="" q.push({x+i,y+j});="" if(!duan())="" {puts("-1");return="" 0;}="" printf("%d\n",num);="">=1;--i) printf("%d %d %d\n",b[i].x,b[i].y,b[i].c); return 0; } 点击查看代码
#include<bits/stdc++.h>
#define ll long  long
#define db double 
using namespace std;
const int N=1010;
int n,m,c[N][N],num;
queue<pair<int,int> >q;
struct wy{int x,y,c;}b[N*N];
inline bool check(int x,int y)
{
    if(x>=1&&x<n&&y>=1&&y<m)
    {
        int mx=max(max(c[x][y],c[x][y+1]),max(c[x+1][y],c[x+1][y+1]));
        if(!mx) return false;
        if(c[x][y]&&c[x][y]!=mx) return false; 
        if(c[x][y+1]&&c[x][y+1]!=mx) return false;
        if(c[x+1][y]&&c[x+1][y]!=mx) return false;
        if(c[x+1][y+1]&&c[x+1][y+1]!=mx) return false;
        return true;
    }
    return false;
}
inline void clear(int x,int y)
{
    c[x][y]=c[x][y+1]=0;
    c[x+1][y]=c[x+1][y+1]=0;
}
inline bool duan()
{
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) if(c[i][j]) return false;
    return true;
}
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) 
        {
            scanf("%d",&c[i][j]);
            if(check(i,j)) q.push({i,j});
        }   
    while(q.size())
    {
        int x=q.front().first,y=q.front().second;
        q.pop();
        if(check(x,y))
        {
            b[++num].x=x;
            b[num].y=y;
            b[num].c=max(max(c[x][y],c[x][y+1]),max(c[x+1][y],c[x+1][y+1]));
            clear(x,y);
            for(int i=-1;i<=1;++i)
                for(int j=-1;j<=1;++j) q.push({x+i,y+j});
        }    
    }    
    if(!duan()) {puts("-1");return 0;}
    printf("%d\n",num); 
    for(int i=num;i>=1;--i) printf("%d %d %d\n",b[i].x,b[i].y,b[i].c);
    return 0;
} 

E. Colorful Operations

上一篇:后台环境搭建-ssm+maven多模块


下一篇:dictionary changed size during iteration