【BZOJ1500】维修数列
想要写题练练手,于是就盯准了这个维修数列...
一直都很害怕写线段树,现在看来用不着写线段树了
写完心情愉悦...然而被求0个数的和之类的数据恶心到了...
总体来说代码一遍敲下来没什么问题还是很鼓舞人心的。
记录一下当时写出错误总结出的心得:
1.Rotate操作时关于每个节点的父亲节点和儿子节点的变更。先更新fa的fa的儿子节点,再更新旋转节点的子节点的fa,然后再处理那两个旋转的节点。
借(chao)鉴(xi)了一下陈老师的代码。
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> typedef long long LL; const int maxn=500010,inf=~0U>>1; using namespace std; struct Node { Node *c[2],*p; int size; int v,sum; int lmax,rmax,vmax; bool tag_same,tag_rev; int samev; bool w() {return p->c[1]==this;} }*root,*Null; namespace Memory { Node Mem[maxn]; Node *Stack[maxn]; int top; void Memory_Init() {for (int i=0;i<maxn;i++) Stack[i]=&Mem[i];top=maxn-1;} void Delete_Node(Node *t) {Stack[++top]=t;} Node* New_Node() {return Stack[top--];} }; struct Splay_Tree { #define ls x->c[0] #define rs x->c[1] void Update(Node *x) { if (x==Null) return; x->sum=ls->sum+rs->sum+x->v; x->size=ls->size+rs->size+1; int L_rmax=max(ls->rmax,0),R_lmax=max(rs->lmax,0); x->lmax=max(ls->lmax,ls->sum+x->v+R_lmax); x->rmax=max(rs->rmax,rs->sum+x->v+L_rmax); x->vmax=max(ls->vmax,rs->vmax); x->vmax=max(x->vmax,L_rmax+x->v+R_lmax); } void Update_Same(Node *x,int samev) { if (x==Null) return; x->v=samev; x->sum=x->size*samev; x->lmax=x->rmax=x->vmax=max(x->sum,samev); x->samev=samev; x->tag_same=1; } void Update_Rev(Node *x) { if (x==Null) return; swap(ls,rs); swap(x->lmax,x->rmax); x->tag_rev^=1; } void Push_Down(Node *x) { if (x->tag_same) { Update_Same(ls,x->samev); Update_Same(rs,x->samev); x->tag_same=0; x->samev=0; } if (x->tag_rev) { Update_Rev(ls); Update_Rev(rs); x->tag_rev=0; } } void Rotate(Node *x) { Node *p=x->p; Push_Down(p);Push_Down(x); bool w=x->w(); p->p->c[p->w()]=x; x->p=p->p;p->c[w]=x->c[!w]; x->c[!w]->p=p; x->c[!w]=p;p->p=x; Update(p); if (p==root) root=x; } void Splay(Node *x,Node *head) { if (x==Null) return; Push_Down(x); while (x->p!=head) if (x->p->p==head) Rotate(x); else if (x->w()==x->p->w()) Rotate(x->p),Rotate(x); else Rotate(x),Rotate(x); Update(x); } Node* Select(int kth) { Node *x=root; while (kth) { Push_Down(x); int lsize=ls->size; if (lsize+1==kth) return x; if (kth>lsize) kth-=lsize+1,x=rs; else x=ls; } return x; } Node* Get_Seq(int l,int r) { if (l==1 && r==root->size) return root; if (l==1 && r< root->size) {Splay(Select(r+1),Null);return root->c[0];} if (l> 1 && r==root->size) {Splay(Select(l-1),Null);return root->c[1];} Splay(Select(l-1),Null); Splay(Select(r+1),root); return root->c[1]->c[0]; } void Mark_Same(Node *x,int samev) { Update_Same(x,samev); Splay(x,Null); } void Mark_Rev(Node *x) { Update_Rev(x); Splay(x,Null); } Node* New_Node(int v) { Node *x=Memory::New_Node(); x->v=v; x->samev=x->tag_same=x->tag_rev=0; return x; } Node* Make_Tree(int *a,int l,int r) { if (l>r) return Null; int mid=(l+r)>>1; Node *x=New_Node(a[mid]); ls=Make_Tree(a,l,mid-1); rs=Make_Tree(a,mid+1,r); if (ls!=Null) ls->p=x; if (rs!=Null) rs->p=x; Update(x); return x; } Splay_Tree() { Memory::Memory_Init(); Null=Memory::New_Node(); Null->v=Null->sum=Null->size=Null->samev=0; Null->tag_same=Null->tag_rev=0; Null->lmax=Null->rmax=Null->vmax=-inf; Null->p=Null->c[0]=Null->c[1]=NULL; root=Null; } void Insert(int *a,int posi,int tot) { Node *x=Make_Tree(a,1,tot); if (root==Null) root=x,root->p=Null,Null->c[0]=root; else if (posi==root->size) { Splay(Select(root->size),Null); root->c[1]=x; x->p=root; Update(root); } else if (posi==0) { Splay(Select(1),Null); root->c[0]=x; x->p=root; Update(root); } else { Splay(Select(posi),Null); Splay(Select(posi+1),root); root->c[1]->c[0]=x; x->p=root->c[1]; Splay(x,Null); } } void Delete_DFS(Node *x) { if (ls!=Null) Delete_DFS(ls); if (rs!=Null) Delete_DFS(rs); Memory::Delete_Node(x); } void Delete(int posi,int tot) { Node *x=Get_Seq(posi,posi+tot-1); if (x==root) root=Null; else x->p->c[x->w()]=Null,Splay(x->p,Null); Delete_DFS(x); } void Make_Same(int posi,int tot,int c) { Node *x=Get_Seq(posi,posi+tot-1); Mark_Same(x,c); Splay(x,Null); } void Make_Rev(int posi,int tot) { Node *x=Get_Seq(posi,posi+tot-1); Mark_Rev(x); Splay(x,Null); } void Get_Sum(int posi,int tot) { Node *x=Get_Seq(posi,posi+tot-1); printf("%d\n",x->sum); Splay(x,Null); } void Max_Sum() { printf("%d\n",(root==Null)?0:root->vmax); } void Print(Node *x) { if (x==Null) {if (x==root) printf("\n");return;} Push_Down(x); Print(ls); printf("%d ",x->v); Print(rs); if (x==root) printf("\n"); } }T; int a[maxn]; char ctr[20]; int n,m; inline void read(int &x) { char ch; int flag=0; while (((ch=getchar())<'0' || ch>'9') && ch!='-'); if (ch=='-') flag=-1,x=0; else flag=1,x=ch-'0'; while ((ch=getchar())<='9' && ch>='0') x=x*10+ch-'0'; x=x*flag; } int main() { read(n),read(m); for (int i=1;i<=n;i++) read(a[i]); T.Insert(a,0,n); for (int i=1;i<=m;i++) { scanf("%s",ctr+1); int tot,posi,c; if (ctr[1]=='I') {read(posi),read(tot);for (int i=1;i<=tot;i++) read(a[i]);T.Insert(a,posi,tot);} else if (ctr[1]=='D') {read(posi),read(tot);T.Delete(posi,tot);} else if (ctr[1]=='R') {read(posi),read(tot);T.Make_Rev(posi,tot);} else if (ctr[1]=='G') {read(posi),read(tot);T.Get_Sum(posi,tot);} else if (ctr[3]=='K') {read(posi),read(tot),read(c);T.Make_Same(posi,tot,c);} else T.Max_Sum(); //T.Print(root); } return 0; }