zoukankan      html  css  js  c++  java
  • [3.30校内训练赛]

    来自FallDream的博客,未经允许,请勿转载,谢谢。

    ---------------------------------------------------

    ditoly这次打好了虐爆我们的主意,掏出三道丧题,囊括三种赛制,第一道丧病oi题,第二道sb交互题,第三道奇怪提答............

    第二道交互题没人做,也挺奇怪的,不讲了;

    第三道是找规律,也就50个数列把,我拿出我最强的找规律水平,用上插值啊快速幂啊矩阵乘法啊肉眼观察法啊乱差分啊等等办法,骗到了48分,貌似全场最高了..得分靠随缘,也不讲了。

    讲讲第一题,给定一个数列,需要支持100种操作。    $n,mleqslant 100000$

    1:查询一段区间,你每次可以任选其中一段区间+1或者-1,求把它变成全是0的最小次数。

    10:区间加一个值。  11:区间翻转   100:回到k次操作之前的状态。  

    看到这题,很明显可以可持久化平衡树,但我姿势不够,不会,而且丧病出题人卡空间。还好脑补了一种乱建边的方法,从一个状态向它能转移到的状态连边,然后dfs,离开时撤销,类似线段树分治。

    然后维护一棵平衡树,修改操作容易维护,查询操作的答案是这个区间差分的绝对值之和加上左右端点的绝对值之和除以2.  我把查询做成了只能-1,爆0了qaq

    #include<iostream>
    #include<cstdio>
    #define MN 100000
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int s[MN+5],n,m,cnt=0;
    struct ques{int kind,l,r,x;ll ans;}q[MN+5];
    struct edge{int to,next;}e[MN+5];
    int fa[MN+5],c[MN+5][2],rt,head[MN+5],size[MN+5];
    ll num[MN+5],ad[MN+5],nl[MN+5],nr[MN+5],sum[MN+5];
    bool rev[MN+5];
    
    template<typename t> t abs(t x){return x<0?-x:x;}
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
    
    void update(int x)
    {
        int l=c[x][0],r=c[x][1];
        nl[x]=(l?nl[l]:num[x]);nr[x]=(r?nr[r]:num[x]);
        size[x]=size[l]+size[r]+1;
        sum[x]=0;
        if(l) sum[x]+=sum[l]+abs(num[x]-nr[l]);
        if(r) sum[x]+=sum[r]+abs(num[x]-nl[r]);
    }
    
    inline void mark(int x,int z)
    {
        nl[x]+=z;nr[x]+=z;
        num[x]+=z;ad[x]+=z;
    }
    
    void pushdown(int x)
    {
        int l=c[x][0],r=c[x][1];
        if(rev[x]) 
        {
            rev[l]^=1;rev[r]^=1;rev[x]^=1;
            swap(c[l][0],c[l][1]);swap(c[r][0],c[r][1]);
            swap(nl[l],nr[l]);swap(nl[r],nr[r]);
        }
        if(ad[x])
        {
            mark(l,ad[x]);mark(r,ad[x]);
            ad[x]=0;
        }
    }
    
    void build(int&x,int l,int r,int last)
    {
        if(l>r) return;
        x=l+r>>1;fa[x]=last;num[x]=s[x];
        if(l==r) 
        {
            size[x]=1;nl[x]=nr[x]=s[x];sum[x]=0;
            return;
        }
        build(c[x][0],l,x-1,x);
        build(c[x][1],x+1,r,x);
        update(x);
    }
    
    void rotate(int x,int&k)
    {
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(y==k) k=x; else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x,int&k)
    {
        while(x!=k)
        {
            int y=fa[x],z=fa[y];
            if(y!=k)
            {
                if(c[z][1]==y^c[y][1]==x) rotate(x,k);
                else rotate(y,k);    
            } 
            rotate(x,k);
        }
    }
    
    int find(int x,int rk)
    {
        pushdown(x);
        int sz=size[c[x][0]]+1;
        if(sz==rk) return x;
        else if(sz<rk) return find(c[x][1],rk-sz);
        else return find(c[x][0],rk);
    }
    
    int split(int l,int r)
    {
        splay(find(rt,l),rt);splay(find(rt,r),c[rt][1]);
        return c[c[rt][1]][0];
    }
    
    void solve(int x)
    {
        if(q[x].kind==1) 
        {
            ll y=sum[split(q[x].l,q[x].r+2)];
            q[x].ans=(1LL*abs(num[find(rt,q[x].l+1)])+abs(num[find(rt,q[x].r+1)])+y)/2;
        }
        if(q[x].kind==10)
        {
            int y=split(q[x].l,q[x].r+2);mark(y,q[x].x); 
            update(c[rt][1]);update(rt);
        }
        if(q[x].kind==11) 
        {
            int y=split(q[x].l,q[x].r+2);
            rev[y]^=1;swap(c[y][0],c[y][1]);
            swap(nl[y],nr[y]);
            update(c[rt][1]);update(rt);
        }
        for(int i=head[x];i;i=e[i].next)
            solve(e[i].to);
        if(q[x].kind==10)
        {
            int y=split(q[x].l,q[x].r+2);
            mark(y,-q[x].x); 
            update(c[rt][1]);update(rt);
        }
        if(q[x].kind==11)
        {
            int y=split(q[x].l,q[x].r+2);
            rev[y]^=1;swap(c[y][0],c[y][1]);
            swap(nl[y],nr[y]);
            update(c[rt][1]);update(rt);
        }
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)s[i+1]=read();
        for(int i=1;i<=m;i++)
        {
            q[i].kind=read();
            if(q[i].kind==1) q[i].l=read(),q[i].r=read();
            if(q[i].kind==10) q[i].l=read(),q[i].r=read(),q[i].x=read();
            if(q[i].kind==11) q[i].l=read(),q[i].r=read();
            if(q[i].kind==100) q[i].x=read(),ins(i-q[i].x-1,i);
            else ins(i-1,i);
        }
        cnt=0;build(rt,1,n+2,0);
        solve(0);
        for(int i=1;i<=m;i++)
            if(q[i].kind==1)
                printf("%lld
    ",q[i].ans);
        return 0;
    }
  • 相关阅读:
    python斐波那契数列
    python装饰器
    Python文件操作
    python 第三方库的安装方法
    Ajax 基本使用学习记录
    微分方程概述
    Typora中的数学公式
    Ubuntu20.04 安装 mysql8.0 之后 root 账户无法登录
    Ubuntu20.04换源之后依旧慢?如何更有效的换源
    Ubuntu18.04更新python版本
  • 原文地址:https://www.cnblogs.com/FallDream/p/xunlian330.html
Copyright © 2011-2022 走看看