萌新刚学oi,求助fhq-treap

P3391 【模板】文艺平衡树

ass_wecan @ 2022-04-03 09:56:05

代码量挺短的,求求神仙们花时间帮蒟蒻看看吧qwq

样例过了全部WA,求助

#include<bits/stdc++.h>
#define printlf(x) print(x),putchar('\n')
#define printsp(x) print(x),putchar(' ')
using namespace std;
const int N=1e5+5;
struct node{
    int s[2];
    int val,siz,rd,tag;
}tree[N];
int num,root,x,y,z;
inline int read(){
    int x=0;
    bool w=0;
    char c=getchar();
    while(!isdigit(c))  w|=c=='-',c=getchar();
    while(isdigit(c))   x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return w?-x:x;
}
inline void print(int x){
    if(x<0) x=-x,putchar('-');
    if(x>9) print(x/10);
    putchar('0'+x%10);
}
inline void push_up(int p){
    tree[p].siz=tree[tree[p].s[0]].siz+tree[tree[p].s[1]].siz+1;
}
inline void push_down(int x){
    swap(tree[x].s[0],tree[x].s[1]);
    tree[tree[x].s[0]].tag^=1;
    tree[tree[x].s[1]].tag^=1;
    tree[x].tag=0;      
}
inline void split(int p,int val,int &x,int &y){
    if(!p){
        x=y=0;
        return ;
    }
    push_down(p);
    if(tree[p].val<=val)    x=p,split(tree[p].s[1],val,tree[p].s[1],y);
    else    y=p,split(tree[p].s[0],val,x,tree[p].s[0]);
    push_up(p); 
}
inline int merge(int x,int y){
    if(!x || !y)    return x+y;
    if(tree[x].rd<tree[y].rd){
        if(tree[x].tag) push_down(x);
        tree[x].s[1]=merge(tree[x].s[1],y);
        push_up(x);
        return x;
    }
    if(tree[y].tag) push_down(y);
    tree[y].s[0]=merge(x,tree[y].s[0]);
    push_up(y);
    return y;
}
inline int Newnode(int x){
    tree[++num].rd=rand(),tree[num].siz=1,tree[num].val=x;
    return num;
}
inline void Insert(int val){
    root=merge(root,Newnode(val));
}
inline void Get_ans(int p){
    if(tree[p].tag) push_down(p);
    if(tree[p].s[0])    Get_ans(tree[p].s[0]);
    printsp(tree[p].val);
    if(tree[p].s[1])    Get_ans(tree[p].s[1]);
}
signed main(){
    int n=read(),m=read();
    for(register int i=1;i<=n;++i){
        Insert(i);
    }
    while(m--){
        int l=read(),r=read();
        split(root,l-1,x,y);
        split(y,r,y,z);
        tree[y].tag^=1;
        root=merge(x,merge(y,z));
    }
    Get_ans(root);
    return 0;
}

by ppip @ 2022-04-03 10:03:28

qndmx


by Francais_Drake @ 2022-04-03 10:05:31

split(y,r,y,z)改成split(y,r-l+1,y,z),在 l~n 的区间内部划出 l~r 的区间应该等效于划出前 (r-l+1) 个数


by Masna_Kimoyo @ 2022-04-03 10:07:55

@ppip ???


by ass_wecan @ 2022-04-03 10:14:02

@Francais_Drake @Francais_Drake 我觉得您可能需要看清楚我的写法(?)


by danielqf @ 2022-04-03 10:20:13

@I_love_xzo @Francais_Drake说的是对的


by Francais_Drake @ 2022-04-03 10:21:43

@I_love_xzo 按大小分裂不是按值分裂,你需要写按大小分裂的split函数,把对应的val改成sizmerge不用更改。题目说了划分出第 l 个到第 r 个数的区间,不是从 l 这个数到 r 这个数的区间。

退一万步来讲反转某区间后序列极有可能是乱序的,按值分裂没有意义


by ass_wecan @ 2022-04-03 10:54:08

@danielqf @Francais_Drake 因为我在题解区看到有个是这么写的/ll/dk

    for(int i=1,x,y;i<=m;i++){
        scanf("%d%d",&x,&y);
        //分成分别以l,p,r为根节点的三棵树 
        split(root,y,l,r);
        split(l,x-1,l,p);
        tree[p].lazy^=1;//更新懒标记,每次的p值会发生改变,只有相同的区间p值才会不同,不用担心 (:^_^:) 
        root=merge(merge(l,p),r);//合并 
    }

by Francais_Drake @ 2022-04-03 11:10:21

@I_love_xzo ta是先分出大小为 r 的区间,从原来分出的大小为 r 的区间再分出大小为 l 的区间剩余的大小为 r-l+1 的区间即为待修区间,也是正确的。

并且ta至少没有把按大小分裂写成按值分裂


|