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
改成siz
。merge
不用更改。题目说了划分出第 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至少没有把按大小分裂写成按值分裂