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


Codeforces Round #771 (Div. 2)

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

A. Reverse

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

点击查看代码
#include
#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
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

C. Inversion Graph

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

点击查看代码
#include
#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_queueq;
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())

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

点击查看代码
#include
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]

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<> >q; struct wy{int x,y,c;}b[N*N]; inline bool check(int x,int y) { if(x>=1&&x=1&&y=1;--i) printf("%d %d %d\n",b[i].x,b[i].y,b[i].c); return 0; } 点击查看代码
#include
#define ll long  long
#define db double 
using namespace std;
const int N=1010;
int n,m,c[N][N],num;
queue >q;
struct wy{int x,y,c;}b[N*N];
inline bool check(int x,int y)
{
    if(x>=1&&x=1&&y=1;--i) printf("%d %d %d\n",b[i].x,b[i].y,b[i].c);
    return 0;
} 

E. Colorful Operations

关于这种线段树的延迟操作,其实之前也是写过类似的题目的.....就是没想到这个题可以这样写。
先把问题简化,如果只有单点修改的话,那我们可以新增一个变量color[],表示某个颜色总的变化量。对于操作一:我们输出a[x]+color[c[x]].对于操作二,color[x]+=v;对于操作一:我们可以a[x]+=color[c[x]];c[x]=k;a[x]-=color[c[x]];这样的话,我们全部操作即可在O(1)操作内完成。
至于变成区间修改的话,大体的想想,因为操作1的原因,整个序列大概率是一段一段连续的数字。那我们可以维护一个区间是否颜色相同,相同的话在上面做修改。不同的话,继续往下找。虽然某个操作的复杂度可能很大,但均摊下去应该不大。.....(具体证明还没有想明白...先这样咕掉...)

点击查看代码
#include
#define ls p<<1
#define rs p<<1|1
#define ll long long
using namespace std;
const int N=1e6+10;
int n,q;
char c[100]; 
ll color[N];
struct Tree
{
    int col;
    bool sa;
    ll la;    
    #define sa(p) t[p].sa
    #define la(p) t[p].la
    #define col(p) t[p].col
}t[N<<2];
inline void build(int p,int l,int r)
{
    sa(p)=1;col(p)=1;
    if(l==r) return;
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);    
} 
inline void push(int p)
{
    if(la(p))
    {
        la(ls)+=la(p);
        la(rs)+=la(p);
        la(p)=0;
    }
    if(sa(p)&&col(p))
    {
        sa(ls)=1;sa(rs)=1;
        col(ls)=col(p);
        col(rs)=col(p);
    }
}
inline ll ask(int p,int l,int r,int x)
{
    if(l==r) return la(p)+color[col(p)];   
    push(p);
    int mid=l+r>>1;
    if(x<=mid) return ask(ls,l,mid,x);
    else return ask(rs,mid+1,r,x);
}
inline void alter(int p,int l,int r,int L,int R,int c)
{
    if(l<=L&&r>=R&&sa(p))
    {
        sa(p)=1;
        la(p)+=color[col(p)]-color[c];
        col(p)=c;
        return;
    }
    push(p);
    int mid=L+R>>1;
    if(l<=mid) alter(ls,l,r,L,mid,c);
    if(r>mid) alter(rs,l,r,mid+1,R,c);
    if(sa(ls)&&sa(rs)&&col(ls)==col(rs)) sa(p)=1,col(p)=col(ls);
    else sa(p)=0;
}
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d%d",&n,&q);
    build(1,1,n);
    for(int i=1;i<=q;++i)
    {
        scanf("%s",c+1);
        if(c[1]=='C') 
        {
            int l,r,c;
            scanf("%d%d%d",&l,&r,&c);
            alter(1,l,r,1,n,c);
        }
        else if(c[1]=='A') 
        {
            int c,x;
            scanf("%d%d",&c,&x);
            color[c]+=x;
        }
        else 
        {
            int x;scanf("%d",&x);
            printf("%lld\n",ask(1,1,n,x));
        }
    }
    return 0;
}
posted @ 2022-02-20 14:48  逆天峰  阅读(2)  评论(0)  编辑  刷新页面返回顶部 Copyright ? 2022 逆天峰
Powered by .NET 6 on Kubernetes 作者:逆天峰 出处:https://www.cnblogs.com/gcfer//