100分玄关求助
查看原帖
100分玄关求助
246316
yanzihe楼主2025/2/4 15:55

如题,这么写 push_down 函数是错的,WA 38分。

void push_down(ll u){
        if(tr[u].mul!=1){
            if(tr[u].l){tr[tr[u].l].mul=-tr[tr[u].l].mul;tr[tr[u].l].ad=-tr[tr[u].l].ad;tr[tr[u].l].val=-tr[tr[u].l].val;}
            if(tr[u].r){tr[tr[u].r].mul=-tr[tr[u].r].mul;tr[tr[u].r].ad=-tr[tr[u].r].ad;tr[tr[u].r].val=-tr[tr[u].r].val;}
            tr[u].mul=1;
            // swap(tr[u].l, tr[u].r);
        }
        if(tr[u].ad!=0){
            if(tr[u].l){tr[tr[u].l].ad+=tr[u].ad;tr[tr[u].l].val+=tr[u].ad;}
            if(tr[u].r){tr[tr[u].r].ad+=tr[u].ad;tr[tr[u].r].val+=tr[u].ad;}
            tr[u].ad=0;
        }
        if(tr[u].l&&tr[tr[u].l].val>tr[u].val||tr[u].r&&tr[tr[u].r].val<tr[u].val){
            swap(tr[u].l, tr[u].r);
        }
    }

但是这么写是正确的,AC100分

void push_down(ll u){
        if(tr[u].mul!=1){
            if(tr[u].l){tr[tr[u].l].mul=-tr[tr[u].l].mul;tr[tr[u].l].ad=-tr[tr[u].l].ad;tr[tr[u].l].val=-tr[tr[u].l].val;}
            if(tr[u].r){tr[tr[u].r].mul=-tr[tr[u].r].mul;tr[tr[u].r].ad=-tr[tr[u].r].ad;tr[tr[u].r].val=-tr[tr[u].r].val;}
            tr[u].mul=1;
            swap(tr[u].l, tr[u].r);
        }
        if(tr[u].ad!=0){
            if(tr[u].l){tr[tr[u].l].ad+=tr[u].ad;tr[tr[u].l].val+=tr[u].ad;}
            if(tr[u].r){tr[tr[u].r].ad+=tr[u].ad;tr[tr[u].r].val+=tr[u].ad;}
            tr[u].ad=0;
        }
        // if(tr[u].l&&tr[tr[u].l].val>tr[u].val||tr[u].r&&tr[tr[u].r].val<tr[u].val){
        //     swap(tr[u].l, tr[u].r);
        // }
    }

这两个 push_down 唯一的区别在与什么时候交换儿子。正确的写法是在区间被翻转时交换左右儿子,错误的写法是在二叉查找树的性质不满足时交换左右儿子,为什么这么写就错了呢?

附:完整正确代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define rrep(i,a,b) for(ll i=(a);i>=(b);i--)
const ll N=2e5+9;
ll n, q;
ll a[N];
vector <pair<ll, ll> > ad[N], jian[N];
mt19937_64 myrand(0);
namespace fast_IO{//快读模板
    #define FASTIO
    #define IOSIZE 100000
    char ibuf[IOSIZE],obuf[IOSIZE];char*p1=ibuf,*p2=ibuf,*p3=obuf;
    #ifdef ONLINE_JUDGE
    #define getchar()((p1==p2)and(p2=(p1=ibuf)+fread(ibuf,1,IOSIZE,stdin),p1==p2)?(EOF):(*p1++))
    #define putchar(x)((p3==obuf+IOSIZE)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
    #endif
    #define isdigit(ch)(ch>47&&ch<58)
    #define isspace(ch)(ch<33)
    template<typename T>inline T read(){T s=0;int w=1;char ch;while(ch=getchar(),!isdigit(ch)and(ch!=EOF))if(ch=='-')w=-1;if(ch==EOF)return false;while(isdigit(ch))s=s*10+ch-48,ch=getchar();return s*w;}template<typename T>inline bool read(T&s){s=0;int w=1;char ch;while(ch=getchar(),!isdigit(ch)and(ch!=EOF))if(ch=='-')w=-1;if(ch==EOF)return false;while(isdigit(ch))s=s*10+ch-48,ch=getchar();return s*=w,true;}inline bool read(char&s){while(s=getchar(),isspace(s));return true;}inline bool read(char*s){char ch;while(ch=getchar(),isspace(ch));if(ch==EOF)return false;while(!isspace(ch))*s++=ch,ch=getchar();*s='\000';return true;}template<typename T>inline void print(T x){if(x<0)putchar('-'),x=-x;if(x>9)print(x/10);putchar(x%10+48);}inline void print(char x){putchar(x);}inline void print(char*x){while(*x)putchar(*x++);}inline void print(const char*x){for(int i=0;x[i];i++)putchar(x[i]);}
    #ifdef _GLIBCXX_STRING
    inline bool read(std::string&s){s="";char ch;while(ch=getchar(),isspace(ch));if(ch==EOF)return false;while(!isspace(ch))s+=ch,ch=getchar();return true;}inline void print(std::string x){for(int i=0,n=x.size();i<n;i++)putchar(x[i]);}
    #endif
    template<typename T,typename...T1>inline int read(T&a,T1&...other){return read(a)+read(other...);}template<typename T,typename...T1>inline void print(T a,T1...other){print(a);print(other...);}struct Fast_IO{~Fast_IO(){fwrite(obuf,p3-obuf,1,stdout);}}io;template<typename T>Fast_IO&operator>>(Fast_IO&io,T&b){return read(b),io;}template<typename T>Fast_IO&operator<<(Fast_IO&io,T b){return print(b),io;}
}using namespace fast_IO;
ll bcj[N];
ll findl(ll u){
    if(bcj[u]==u)return u;
    return bcj[u]=findl(bcj[u]);

}
struct treap{
    // ll pos[N];//代表标记为i的点现在在tr数组中的下标
    struct point{
        ll val, key, l, r, fa, mul, ad;//id是标记, 先乘再加,val是真实值
    }tr[N*32];
    ll rt;
    ll nN;
    void push_down(ll u){
        if(tr[u].mul!=1){
            if(tr[u].l){tr[tr[u].l].mul=-tr[tr[u].l].mul;tr[tr[u].l].ad=-tr[tr[u].l].ad;tr[tr[u].l].val=-tr[tr[u].l].val;}
            if(tr[u].r){tr[tr[u].r].mul=-tr[tr[u].r].mul;tr[tr[u].r].ad=-tr[tr[u].r].ad;tr[tr[u].r].val=-tr[tr[u].r].val;}
            tr[u].mul=1;
            swap(tr[u].l, tr[u].r);
        }
        if(tr[u].ad!=0){
            if(tr[u].l){tr[tr[u].l].ad+=tr[u].ad;tr[tr[u].l].val+=tr[u].ad;}
            if(tr[u].r){tr[tr[u].r].ad+=tr[u].ad;tr[tr[u].r].val+=tr[u].ad;}
            tr[u].ad=0;
        }
        // if(tr[u].l&&tr[tr[u].l].val>tr[u].val||tr[u].r&&tr[tr[u].r].val<tr[u].val){
        //     swap(tr[u].l, tr[u].r);
        // }
    }
    void split(ll u, ll v, ll &x, ll &y, ll xfa=0, ll yfa=0){
        if(u==0){x=y=0;return;}
        push_down(u);
        if(tr[u].val<=v){
            tr[u].fa=xfa;
            x=u;
            split(tr[u].r, v, tr[u].r, y, u, yfa);
        }else{
            tr[u].fa=yfa;
            y=u;
            split(tr[u].l, v, x, tr[u].l, xfa, u);
        }
    }
    ll merge(ll u, ll v){
        if(u==0||v==0)return u+v;
        push_down(u);push_down(v);
        if(tr[u].key>tr[v].key){
            tr[u].r=merge(tr[u].r, v);
            tr[tr[u].r].fa=u;
            return u;
        }else{
            tr[v].l=merge(u, tr[v].l);
            tr[tr[v].l].fa=v;
            return v;
        }
    }
    void insert(ll id, ll val){
        ll curu=id;
        tr[curu]=(point){val, myrand(), 0, 0, 0, 1, 0};
        ll x=0, y=0;
        split(rt, val, x, y);
        rt=merge(merge(x, curu), y);
    }
    void dfs(ll u, ll other){
        if(u==0)return;
        bcj[findl(u)]=findl(other);
        dfs(tr[u].l, other);
        dfs(tr[u].r, other);
    }
    ll mergeWithIntersection(ll u, ll v){
        if(u==0||v==0)return u+v;
        push_down(u);push_down(v);
        if(tr[u].key<tr[v].key){swap(u, v);}
        ll x=0, y=0, z=0;
        split(v, tr[u].val-1, x, y);
        split(y, tr[u].val, y, z);
        dfs(y, u);
        // split(v, tr[u].val, x, z);
        tr[u].l=mergeWithIntersection(tr[u].l, x);
        tr[u].r=mergeWithIntersection(tr[u].r, z);
        if(tr[u].l)tr[tr[u].l].fa=u;
        if(tr[u].r)tr[tr[u].r].fa=u;
        return u;
    }
    void replace(ll a){
        ll x=0, y=0;
        split(rt, (a>>1), x, y);
        tr[x].mul*=-1;tr[x].ad*=-1;tr[x].val*=-1;
        tr[x].ad+=a;tr[x].val+=a;
        rt=mergeWithIntersection(x, y);
    }
    ll findwithID(ll id){
        ll u=findl(id);
        ll val=tr[u].val;
        u=tr[u].fa;

        while(u){
            if(tr[u].mul==-1)val=-val;
            val+=tr[u].ad;
            u=tr[u].fa;
        }
        return val;
    }
    void print(ll u){
        push_down(u);
        // cout << tr[u].fa << ' ' << tr[u].val << ' ' << tr[u].id << ' ' << tr[u].mul << ' ' << tr[u].ad << ' ' << tr[u].l << ' ' << tr[u].r << " ; ";
        if(tr[u].l&&tr[tr[u].l].val>tr[u].val)cout << "wrong " << endl;
        if(tr[u].r&&tr[tr[u].r].val<tr[u].val)cout << "wrong " << endl;
        if(tr[u].l)print(tr[u].l);
        if(tr[u].r)print(tr[u].r);
    }
}tree;
ll ans[N];
int main(){
    // freopen("produce.out", "r", stdin);
    // freopen("lyl.out", "w", stdout);
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    io >> n >> q;
    rep(i, 1, q)bcj[i]=i;
    rep(i, 1, n) io >> a[i];
    rep(i, 1, q){
        ll x, l, r;io >> x >> l >> r;
        ad[l].emplace_back(make_pair(x, i));
        jian[r+1].emplace_back(make_pair(x, i));
    }
    rep(i, 1, n+1){
        for(auto v:ad[i]){
            tree.insert(v.second, v.first);
        }
        for(auto v:jian[i]){
            ans[v.second]=tree.findwithID(v.second);
        }
        tree.replace(a[i]);

    }
    rep(i, 1, q)io << ans[i] << '\n';
    // cerr << "Time used: " << clock()*1.0/CLOCKS_PER_SEC << "s" << endl;
    return 0;
}
2025/2/4 15:55
加载中...