题面
题解
一道平衡树的复杂细节题。我用的非旋Treap
R k 把整棵树从中间n - k - 1后面分开,再倒转顺序合并
F 把2~n翻转过来,用懒标记
S i j 使i < j 相当于revolve(i,j,1) , revolve(i+1,j,j - i - 1)
P i j x 还是用懒标记,j可能小于i
C 查询root,要判首尾。
CS i j 查询一段,不判首尾,j可能小于i。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL long long
#define MAXN 500000 + 5
using namespace std;
inline LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
return x * f;
}
LL n,m,i,j,s,o,k,cnt,root,root2,MINN;
bool flag = 0;
struct npair{
LL p[2];
npair(){p[0] = p[1] = 0;}
npair(LL l,LL r){p[0] = l;p[1] = r;}
};
struct tr{
LL s[2],fa;
LL key;
LL heap,siz,lz,me,la,ra,a,lzc;
tr(){key = 0;s[0] = s[1] = 0;heap = 0;siz = 0;lz = 0;me = 0;la = ra = a = 0;fa = 0;lzc = 0;}
}tre[MAXN];
int newnode(int nm) {
tre[++cnt] = tr();
tre[cnt].me = nm;
tre[cnt].a = 1;
tre[cnt].la = nm;
tre[cnt].ra = nm;
tre[cnt].heap = unsigned(rand()) + 1;
tre[cnt].siz = 1;
return cnt;
}
void update(int x) {
tre[0] = tr();
if(x == 0) return ;
tre[x].siz = 1 + tre[tre[x].s[0]].siz + tre[tre[x].s[1]].siz;
int l = tre[x].s[0],r = tre[x].s[1];
if(tre[x].lzc) {
tre[x].a = 1;
tre[x].ra = tre[x].la = tre[x].me;
}
else {
int c1 = (tre[x].lz ? tre[l].ra:tre[l].la);
int c2 = (tre[x].lz ? tre[l].la:tre[l].ra);
int c3 = (tre[x].lz ? tre[r].ra:tre[r].la);
int c4 = (tre[x].lz ? tre[r].la:tre[r].ra);
tre[x].a = 1 + tre[l].a + tre[r].a - (c2 == tre[x].me ? 1:0) - (tre[x].me == c3 ? 1:0);
tre[x].la = (c1 == 0 ? tre[x].me:c1);
tre[x].ra = (c4 == 0 ? tre[x].me:c4);
}
tre[l].fa = tre[r].fa = x;
}
void change(int x) {
if(x) {
tre[x].lz ^= 1;
swap(tre[x].s[0],tre[x].s[1]);
update(x);
}
}
void modify(int x,int cl) {
if(x) {
tre[x].lzc = 1;
tre[x].me = cl;
tre[x].a = 1;
tre[x].la = cl;
tre[x].ra = cl;
}
}
void pushdown(int x) {
if(tre[x].lz) {
tre[x].lz = 0;
change(tre[x].s[0]);
change(tre[x].s[1]);
}
if(tre[x].lzc) {
tre[x].lzc = 0;
modify(tre[x].s[0],tre[x].me);
modify(tre[x].s[1],tre[x].me);
}
}
npair spli(int x,int m) {
npair as;
if(x == 0) return as;
int d = (tre[tre[x].s[0]].siz + 1 <= m);
pushdown(x);
if(d) as = spli(tre[x].s[1],m - tre[tre[x].s[0]].siz - 1);
else as = spli(tre[x].s[0],m);
tre[x].s[d] = as.p[d^1];
update(x);
as.p[d^1] = x;
return as;
}
int merg(int p1,int p2) {
if(!p1) return p2;
if(!p2) return p1;
if(tre[p1].heap < tre[p2].heap) {
pushdown(p1);
tre[p1].s[1] = merg(tre[p1].s[1],p2);
update(p1);
return p1;
}
else {
pushdown(p2);
tre[p2].s[0] = merg(p1,tre[p2].s[0]);
update(p2);
return p2;
}
}
int supersplay(int x,int ml,int mr) {
npair f1 = spli(x,mr);
npair f2 = spli(f1.p[0],ml - 1);
change(f2.p[1]);
return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int ins(int x,int m,int nm) {
npair f1 = spli(x,m);
return merg(merg(f1.p[0],newnode(nm)),f1.p[1]);
}
int del(int x,int m) {
npair f1 = spli(x,m);
npair f2 = spli(f1.p[0],m - 1);
return merg(f2.p[0],f1.p[1]);
}
int idp(int &x,int m) {
npair f1 = spli(x,m);
npair f2 = spli(f1.p[0],m - 1);
int as = f2.p[1];
x = merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
return as;
}
int rerun(int x,int t) {
int n = tre[x].siz;t = (t - 1) % n + 1;
npair f1 = spli(x,n - t);
return merg(f1.p[1],f1.p[0]);
}
int partrun(int x,int l,int r,int t) {
npair f1 = spli(x,r);
npair f2 = spli(f1.p[0],l - 1);
f2.p[1] = rerun(f2.p[1],t);
return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int addk(int x,int l,int r,int cl) {
npair f1 = spli(x,r);
npair f2 = spli(f1.p[0],l - 1);
modify(f2.p[1],cl);
return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int addoutk(int x,int l,int r,int cl) {
npair f1 = spli(x,r);
npair f2 = spli(f1.p[0],l - 1);
modify(f1.p[1],cl);
modify(f2.p[0],cl);
return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int getmin(int x,int l,int r) {
npair f1 = spli(x,r);
npair f2 = spli(f1.p[0],l - 1);
MINN = tre[f2.p[1]].a;
return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
int getoutmin(int x,int l,int r) {
npair f1 = spli(x,r);
npair f2 = spli(f1.p[0],l - 1);
MINN = tre[f1.p[1]].a + tre[f2.p[0]].a - (tre[f1.p[1]].ra == tre[f2.p[0]].la ? 1:0);
return merg(merg(f2.p[0],f2.p[1]),f1.p[1]);
}
void print(int x) {
if(x == 0) return ;
pushdown(x);
print(tre[x].s[0]);
printf("%d(%d,%d)[a:%d c:%d l:%d r:%d] ",x,tre[x].s[0],tre[x].s[1],tre[x].a,tre[x].me,tre[x].la,tre[x].ra);
print(tre[x].s[1]);
update(x);
}
int main() {
n = read();m = read();
for(int i = 1;i <= n;i ++) {
root = ins(root,i - 1,read());
}
int T = read();
char ss[10];
while(T --) {
scanf("%s",ss + 1);
// cout<<"ok"<<endl;
if(ss[1] == 'R') {
k = read();
root = rerun(root,k);
}
else if(ss[1] == 'F') {
root = supersplay(root,2,n);
}
else if(ss[1] == 'S') {
s = read();o = read();
if(s > o) swap(s,o);
if(s != o)
root = partrun(root,s,o,1),root = partrun(root,s + 1,o,o - s - 1);
}
else if(ss[1] == 'P') {
s = read();o = read();k = read();
if(s <= o)root = addk(root,s,o,k);
else root = addoutk(root,o + 1,s - 1,k);
}
else if(ss[1] == 'C' && ss[2] == 'S') {
s = read();o = read();
if(s > o) {
root = getoutmin(root,o + 1,s - 1);
}
else root = getmin(root,s,o);
printf("%d\n",MINN);
}
else if(ss[1] == 'C') {
MINN = tre[root].a;
printf("%d\n",MINN - (tre[root].la == tre[root].ra && MINN > 1 ? 1:0));
}
else if(ss[1] == 'D') {
print(root);putchar('\n');
}
}
return 0;
}