LOJ传送门
洛谷传送门
解析:
很久没有写过平衡树了,恢复一下手感。
FHQ_treap本身好写且常数不大。这道题只需要维护区间翻转,每次提取一个区间只需要按照 s i z siz siz关键字 s p l i t split split出需要操作的序列部分来,然后该打标记的打标记,该下传的时候下传就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<18|1;
char buf[Rlen],*p1,*p2;
char obuf[Rlen],*p3=obuf;
char ch[23];
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline void put_char(char c){
using namespace IOONLY;
*p3++=c;
if(p3==obuf+Rlen)fwrite(obuf,1,Rlen,stdout),p3=obuf;
}
inline void FLUSH(){
using namespace IOONLY;
fwrite(obuf,1,p3-obuf,stdout),p3=obuf;
}
inline int getint(){
re int num;
re char c;
re bool f=0;
while(!isdigit(c=gc()))if(c=='-')f=1;num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
inline void outint(ll a){
using namespace IOONLY;
if(a==0)pc('0');
if(a<0)pc('-'),a=-a;
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
}
using namespace IO;
cs int N=100005;
namespace FHQ_treap{
namespace Vars{
int son[N][2];
int val[N];
int siz[N];
char pri[N];
bool rev[N];
int tot;
}
inline int newnode(int _val){
using namespace Vars;
int now=++tot;
son[now][0]=son[now][1]=0;
val[now]=_val;
siz[now]=1;
rev[now]=0;
pri[now]=rand();
return now;
}
inline void pushup(int now){
using namespace Vars;
siz[now]=siz[son[now][0]]+siz[son[now][1]]+1;
}
inline void pushdown(int now){
using namespace Vars;
if(rev[now]){
swap(son[now][0],son[now][1]);
if(son[now][0])rev[son[now][0]]^=1;
if(son[now][1])rev[son[now][1]]^=1;
rev[now]=0;
}
}
pair<int,int> split_siz(int now,cs int &key){
using namespace Vars;
if(!now)return make_pair(0,0);
pushdown(now);
pair<int,int> res;
if(key<siz[son[now][0]]+1){
res=split_siz(son[now][0],key);
son[now][0]=res.second;
res.second=now;
}
else {
res=split_siz(son[now][1],key-siz[son[now][0]]-1);
son[now][1]=res.first;
res.first=now;
}
pushup(now);
return res;
}
int merge(int lc,int rc){
using namespace Vars;
if(!lc||!rc)return lc+rc;
pushdown(lc),pushdown(rc);
if(pri[lc]<pri[rc]){
son[lc][1]=merge(son[lc][1],rc);
pushup(lc);
return lc;
}
else {
son[rc][0]=merge(lc,son[rc][0]);
pushup(rc);
return rc;
}
}
inline int rev_range(int now,int l,int r){
using namespace Vars;
pair<int,int> res1=split_siz(now,r);
pair<int,int> res2=split_siz(res1.first,l-1);
rev[res2.second]^=1;
return merge(merge(res2.first,res2.second),res1.second);
}
void inorder_dfs(int now){
using namespace Vars;
if(!now)return ;
pushdown(now);
inorder_dfs(son[now][0]);
outint(val[now]),pc(' ');
inorder_dfs(son[now][1]);
}
int build(int l,int r){
if(l==r)return newnode(l);
int mid=(l+r)>>1;
return merge(build(l,mid),build(mid+1,r));
}
}
using namespace FHQ_treap;
int root,n,m;
signed main(){
srand(time(0));
n=getint(),m=getint();
root=build(1,n);
while(m--){
int l=getint(),r=getint();
root=rev_range(root,l,r);
}
inorder_dfs(root);
FLUSH();
return 0;
}