#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
typedef long double ldb;
const int N = 300005;
int n, m;
struct node {
node *fa, *ch[2];
int val, sum;
bool rev;
node(){
fa = ch[0] = ch[1] = NULL;
val = sum = 0;
rev = 0;
}
bool which(){
return fa->ch[1] == this;
}
bool isroot(){
return fa == NULL || (fa->ch[0] != this && fa->ch[1] != this);
}
void upt(){
sum = val;
if(ch[0] != NULL) sum ^= ch[0]->sum;
if(ch[1] != NULL) sum ^= ch[1]->sum;
}
void pushdown(){
if(!rev) return;
swap(ch[0], ch[1]);
if(ch[0] != NULL) ch[0]->rev ^= 1;
if(ch[1] != NULL) ch[1]->rev ^= 1;
rev = 0;
}
} s[N];
void rotate(node *u){
node *v = u->fa, *w = v->fa, *b = u->ch[!u->which()];
if(!v->isroot()) w->ch[v->which()] = u;
u->which() ? (u->ch[0] = v, v->ch[1] = b) : (u->ch[1] = v, v->ch[0] = b);
u->fa = w, v->fa = u;
if(b != NULL) b->fa = v;
v->upt();
}
void splay(node *u){
static node *stk[N];
int top;
stk[top = 1] = u;
while(!stk[top]->isroot()) stk[top + 1] = stk[top]->fa, top++;
while(top) stk[top--]->pushdown();
while(!u->isroot()){
if(!u->fa->isroot()){
if(u->which() == u->fa->which()) rotate(u->fa);
else rotate(u);
}
rotate(u);
}
u->upt();
}
void access(node *u){
node *v = NULL;
while(u != NULL){
splay(u);
u->ch[1] = v;
u->upt();
v = u;
u = u->fa;
}
}
void makeroot(node *u){
access(u);
splay(u);
u->rev ^= 1;
}
node *findroot(node *u){
access(u);
splay(u);
while(u->pushdown(), u->ch[0] != NULL)
u = u->ch[0];
splay(u);
return u;
}
void link(node *u, node *v){
if(findroot(u) == findroot(v)) return;
makeroot(v);
v->fa = u;
}
void cut(node *u, node *v){
makeroot(u);
access(v);
splay(v);
if(v->ch[0] == u)
v->ch[0] = u->fa = NULL;
}
int query(node *u, node *v){
makeroot(u);
access(v);
splay(v);
return v->sum;
}
void change(node *u, int x){
splay(u);
u->val = x;
u->upt();
}
int main(){
read(n), read(m);
for(int i = 1; i <= n; i++)
read(s[i].val), s[i].upt();
int op, x, y;
while(m--){
read(op), read(x), read(y);
if(op == 0) write(query(s + x, s + y)), enter;
else if(op == 1) link(s + x, s + y);
else if(op == 2) cut(s + x, s + y);
else change(s + x, y);
}
return 0;
}
然而时隔多年,我也终于写出了自己的SPLAY指针板
写完过后突然发现也不是很难,只是要特别注意zero的调用
这是洛谷的P4146 系列终结者
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
struct node
{
node *son[2],*father;
int maxa,tag,num,flag,size;
}pool[1000005],*tail=pool,*root,*zero;
int n,m,shu1,shu2,shu3,shu4;
void update(node *nd)
{
nd->size=nd->son[0]->size+nd->son[1]->size+1;
if(nd->son[0]!=zero&&nd->son[1]!=zero)
nd->maxa=max(nd->num,max(nd->son[0]->maxa,nd->son[1]->maxa));
else if(nd->son[0]!=zero)
nd->maxa=max(nd->num,nd->son[0]->maxa);
else if(nd->son[1]!=zero)
nd->maxa=max(nd->num,nd->son[1]->maxa);
else nd->maxa=nd->num;
}
void pushdown(node *nd)
{
if(nd->flag)
{
swap(nd->son[0],nd->son[1]);
if(nd->son[0]!=zero)
nd->son[0]->flag^=1;
if(nd->son[1]!=zero)
nd->son[1]->flag^=1;
nd->flag=0;
}
if(nd->tag)
{
if(nd->son[0]!=zero)
{
nd->son[0]->maxa+=nd->tag;
nd->son[0]->num+=nd->tag;
nd->son[0]->tag+=nd->tag;
}
if(nd->son[1]!=zero)
{
nd->son[1]->maxa+=nd->tag;
nd->son[1]->num+=nd->tag;
nd->son[1]->tag+=nd->tag;
}
nd->tag=0;
}
}
void init()
{
zero=tail++;
zero->son[0]=zero->son[1]=zero->father=zero;
zero->num=zero->maxa=zero->size=zero->tag=0;
}
node *build(int l,int r)
{
if(l>r) return zero;
node *nd=tail++;
nd->maxa=nd->num=0;
int mid=(l+r)>>1;
nd->son[0]=build(l,mid-1);
nd->son[1]=build(mid+1,r);
if(nd->son[0]!=zero)
nd->son[0]->father=nd;
if(nd->son[1]!=zero)
nd->son[1]->father=nd;
update(nd);
return nd;
}
node *find(int x)
{
node *now=root;
while(1)
{
pushdown(now);
if(now->son[0]->size>=x) now=now->son[0];
else if(now->son[0]->size+1==x) return now;
else x-=now->son[0]->size+1,now=now->son[1];
}
}
void rotate(node *nd)
{
node *p=nd->father;
node *pp=p->father;
int another=pp->son[1]==p;
int kind=(p->son[0]==nd);
node *s=nd->son[kind];
if(s!=zero)
s->father=p;
p->son[!kind]=s;
if(pp!=zero)
nd->father=pp;
else root=nd,nd->father=zero;
if(pp!=zero)
pp->son[another]=nd;
nd->son[kind]=p;
p->father=nd;
update(p);
update(nd);
}
void splay(node *nd,node *pre)
{
while(nd->father!=pre)
{
node *p=nd->father;
if(p->father==pre)
{
rotate(nd);
break;
}
node *pp=p->father;
if((pp->son[1]==p)==(p->son[1]==nd))
{
rotate(p);
rotate(nd);
}
else
{
rotate(nd);
rotate(nd);
}
}
}
void modify(int l,int r,int delta)
{
node *r1=find(l);
node *r2=find(r+2);
splay(r1,zero);
splay(r2,r1);
r2->son[0]->tag+=delta;
r2->son[0]->num+=delta;
r2->son[0]->maxa+=delta;
}
void reverse(int l,int r)
{
node *r1=find(l);
node *r2=find(r+2);
splay(r1,zero);
splay(r2,r1);
r2->son[0]->flag^=1;
}
int query(int l,int r)
{
node *r1=find(l);
node *r2=find(r+2);
splay(r1,zero);
splay(r2,r1);
return r2->son[0]->maxa;
}
int main()
{
cin>>n>>m;
init();
root=build(1,n+2);
root->father=zero;
for(int i=1;i<=m;i++)
{
scanf("%d",&shu1);
if(shu1==1)
{
scanf("%d%d%d",&shu2,&shu3,&shu4);
modify(shu2,shu3,shu4);
}
else if(shu1==2)
{
scanf("%d%d",&shu2,&shu3);
reverse(shu2,shu3);
}
else
{
scanf("%d%d",&shu2,&shu3);
printf("%d\n",query(shu2,shu3));
}
}
return 0;
}