luogu P2042
Posted johnran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2042相关的知识,希望对你有一定的参考价值。
主要是贴一下维护序列的板子:
#include<bits/stdc++.h>
using namespace std;
const int N = 1000005;
const int inf = 1e8+1;
const int NONE = 1e9;
#define ls(x) (bst[x].ch[0])
#define rs(x) (bst[x].ch[1])
#define getKey(x) (bst[x].key)
#define getSize(x) (bst[x].sz)
#define getFather(x) (bst[x].f)
struct splayNode{
int ch[2];
int f;
int sz;
int key;
int tag;
int rev;
int sum;
int left;
int right;
int middle;
void clear(){ch[0]=ch[1]=f=rev=0;tag=NONE;}
}bst[N];
inline bool getDir(int x){return rs(getFather(x))==x;}
int rt, cntNode, top, a[N], id[N], rub[N], n, m;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
int getId(){//防止节点过多,我们需要设置一个垃圾堆,有废弃的节点应该优先使用
if(top==0)return ++cntNode;
return rub[top--];
}
void changeVal(int nd, int val){
if(!nd)return;
bst[nd].tag=bst[nd].key=val;
bst[nd].sum=val*getSize(nd);
bst[nd].left=bst[nd].right=max(bst[nd].sum,0);
bst[nd].middle=max(bst[nd].sum,val);
}
void changeRev(int nd){
swap(ls(nd),rs(nd));
swap(bst[nd].left,bst[nd].right);
bst[nd].rev^=1;
}
void pushup(int nd){
splayNode& x=bst[bst[nd].ch[0]], &y=bst[bst[nd].ch[1]];
splayNode& res=bst[nd];
int val=bst[nd].key;
res.sum=x.sum+y.sum+val;
res.sz=x.sz+y.sz+1;
res.middle=max(max(x.middle,y.middle),x.right+y.left+val);
res.left=max(x.left,x.sum+val+y.left);
res.right=max(y.right,y.sum+val+x.right);
//cout<<"pushup: "<<nd<<" "<<res.sum<<" "<<res.left<<" "<<res.right<<endl;
}
void pushdown(int nd){
if(bst[nd].tag!=NONE){//赋值标记
changeVal(ls(nd),bst[nd].tag);
changeVal(rs(nd),bst[nd].tag);
bst[nd].tag=NONE;
}
if(bst[nd].rev){
changeRev(ls(nd));
changeRev(rs(nd));
bst[nd].rev=0;
}
}
void rot(int nd){
int fa=getFather(nd),gf=getFather(fa);
int ws=getDir(nd),ws1=getDir(fa);
int nd1=bst[nd].ch[ws^1];
bst[fa].ch[ws]=nd1;bst[nd1].f=fa;
bst[gf].ch[ws1]=nd;bst[nd].f=gf;
bst[nd].ch[ws^1]=fa;bst[fa].f=nd;
pushup(fa);pushup(nd);
}
void splay(int nd, int goal=0){
while(getFather(nd)!=goal){
int fa=getFather(nd);
int gf=getFather(fa);
if(gf!=goal){
if(getDir(nd)==getDir(fa))rot(fa);
else rot(nd);
}
rot(nd);
}
if(!goal)rt=nd;
}
int kth(int k){
int nd=rt;
while(1){
pushdown(nd);
if(getSize(ls(nd))>=k)nd=ls(nd);
else if(k==getSize(ls(nd))+1)return nd;
else{
k-=getSize(ls(nd))+1;
nd=rs(nd);
}
}
}
int split(int s, int len){//拆出响应的区间
int x=kth(s),y=kth(s+len+1);
splay(x,0);splay(y,x);
return ls(y);
}
void newNode(int nd, int x){//newc出一新节点
bst[nd].middle=bst[nd].sum=x;
bst[nd].tag=NONE;bst[nd].rev=0;
bst[nd].left=bst[nd].right=max(x,0);
bst[nd].sz=1;
}
void build(int s, int e, int fa){
int mid=(s+e)>>1;int curNode=id[mid],pre=id[fa];
if(s==e){
newNode(curNode,a[s]);
}
if(s<mid)build(s,mid-1,mid);
if(mid<e)build(mid+1,e,mid);
bst[curNode].key=a[mid];bst[curNode].f=pre;bst[curNode].tag=NONE;
pushup(curNode);
bst[pre].ch[mid>=fa]=curNode;
}
void Insert(int s, int len){//先建树,再插入
for(int i=1;i<=len;++i)a[i]=read();
for(int i=1;i<=len;++i)id[i]=getId();
build(1,len,0);
int z=id[(1+len)>>1];
int x=kth(s+1),y=kth(s+2);
splay(x,0);splay(y,x);
getFather(z)=y;ls(y)=z;
pushup(y);pushup(x);
}
void removeTree(int nd){
if(ls(nd))removeTree(ls(nd));
if(rs(nd))removeTree(rs(nd));
rub[++top]=nd;bst[nd].clear();
}
void del(int x, int len){
int nd=split(x,len);int y=getFather(nd);
removeTree(nd),ls(y)=0;
pushup(y);pushup(getFather(y));
}
void update(int x, int len, int val){
int nd=split(x,len),y=getFather(nd);
changeVal(nd,val);
pushup(y),pushup(getFather(y));
}
void reverseTree(int x, int len){
int nd=split(x,len),y=getFather(nd);
if(bst[nd].tag!=NONE)return;//区间被整体赋值了
changeRev(nd);
pushup(y);pushup(getFather(y));
}
int query(int x, int len){//求和
int nd=split(x,len);
return bst[nd].sum;
}
int main(){
n=read(),m=read();
bst[0].middle=a[1]=a[n+2]=-inf;
for(int i=2;i<=n+1;++i)a[i]=read();
for(int i=1;i<=n+2;++i)id[i]=i;
build(1,n+2,0);
rt=(n+3)>>1;cntNode=n+2;
char s[25];
int opt,start,num,val;
for(int i=1;i<=m;++i){
scanf("%s",s+1);
if(s[1]==‘I‘){
start=read();num=read();
Insert(start,num);
}else if(s[1]==‘D‘){
start=read();num=read();
del(start,num);
}else if(s[1]==‘M‘&&s[3]==‘K‘){
start=read();num=read();val=read();
update(start,num,val);
}else if(s[1]==‘M‘&&s[3]==‘X‘){
cout<<bst[rt].middle<<endl;
}else if(s[1]==‘R‘){
start=read(),num=read();
reverseTree(start,num);
}else{
start=read();num=read();
cout<<query(start,num)<<endl;
}
}
return 0;
}
以上是关于luogu P2042的主要内容,如果未能解决你的问题,请参考以下文章