BZOJ 1500 NOI2005 维修数列 题解

题目大意:要求维护一个序列,支持插入,删除,修改(将一段区间内的数全部设置为c),区间翻转,区间求和,区间最大和。

splay维护。其中区间最大和用一个mmax值来记录,需要用lmax和rmax来辅助(代表前缀最大和和后缀最大和)。

mmax有三种情况:区间全部在左子树中,区间全部在右子树中,区间跨越左右子树。

lmax有两种情况:区间全部在左子树中,区间跨越左右子树。这样更新一下即可。

(更新的时候有一些小细节,详见代码)

注意Reverse操作。mmax不变,lmax和rmax交换。注意这题因为有附加值,不能像SuperMemo那题一样翻转时只修改标记,下传的时候再真正修改。

注意操作结束之后要对父亲进行maintain维护。(不过在MakeSame和Reverse操作之后不maintain也可以,不知道为什么)

(不过maintain操作是O(1)的,多maintain几次没坏处...)

  1 #include<cstdio>
  2 #include<algorithm>
  3 const int MAXN=1000000+10;
  4 const int INF=~0U>>1;
  5 int a[MAXN];
  6 struct Node{
  7     int s,v;
  8     int lmax,rmax,mmax,sum;
  9     bool rev,same;
 10     Node* p,*ch[2];
 11     Node() {same=sum=s=v=rev=0;lmax=rmax=mmax=-INF;}
 12     inline void maintain()
 13     {
 14         s=ch[0]->s+ch[1]->s+1;
 15         sum=v+ch[0]->sum+ch[1]->sum;
 16         lmax=std::max(ch[0]->lmax,ch[0]->sum+v+std::max(0,ch[1]->lmax));
 17         rmax=std::max(ch[1]->rmax,ch[1]->sum+v+std::max(0,ch[0]->rmax));
 18         mmax=std::max(std::max(ch[0]->mmax,ch[1]->mmax),std::max(0,ch[0]->rmax)+v+std::max(0,ch[1]->lmax));
 19     }
 20     inline void setc(Node* t,bool d)
 21     {
 22         ch[d]=t;
 23         t->p=this;
 24     }
 25     inline void MakeSame(int sv)
 26     {
 27         v=sv;
 28         same=1;
 29         sum=s*sv;
 30         mmax=rmax=lmax=std::max(v,sum);
 31     }
 32     inline void revIt()
 33     {
 34         std::swap(ch[0],ch[1]);
 35         std::swap(lmax,rmax);
 36         rev^=1;
 37     }
 38     inline bool d() {return p->ch[1]==this;}
 39     inline void pushdown();
 40 }Tnull,*null=&Tnull;
 41 inline void Node::pushdown()
 42 {
 43     if(rev)
 44     {
 45         if(ch[0]!=null) ch[0]->revIt();
 46         if(ch[1]!=null) ch[1]->revIt();
 47         rev=0;
 48     }
 49     if(same)
 50     {
 51         if(ch[0]!=null) ch[0]->MakeSame(v);
 52         if(ch[1]!=null) ch[1]->MakeSame(v);
 53         same=0;
 54     }
 55 }
 56 Node* root;
 57 inline void rot(Node* t)
 58 {
 59     Node* p=t->p;
 60     p->pushdown();t->pushdown();
 61     bool d=t->d();
 62     p->p->setc(t,p->d());
 63     p->setc(t->ch[d^1],d);
 64     t->setc(p,d^1);
 65     p->maintain();
 66     if(p==root)
 67         root=t;
 68 }
 69 void splay(Node* t,Node* f=null)
 70 {
 71     while(t->p!=f)
 72     {
 73         if(t->p->p==f) rot(t);
 74         else t->d()==t->p->d()?(rot(t->p),rot(t)):(rot(t),rot(t));
 75     }
 76     t->maintain();
 77 }
 78 Node* select(int k)
 79 {
 80     for(Node* t=root;;)
 81     {
 82         t->pushdown();
 83         int s=t->ch[0]->s;
 84         if(k==s) return t;
 85         if(k>s) k-=s+1,t=t->ch[1];
 86         else t=t->ch[0];
 87     }
 88 }
 89 inline Node*& get(int l,int r) //[l,r)
 90 {
 91     Node* L=select(l-1);
 92     Node* R=select(r);
 93     splay(L);
 94     splay(R,L);
 95     return R->ch[0];
 96 }
 97 void DeleteTree(Node*& t)
 98 {
 99     if(t==null) return;
100     DeleteTree(t->ch[0]);
101     DeleteTree(t->ch[1]);
102     delete t;
103     t=null;
104 }
105 Node* build(int l,int r) //[l,r)
106 {
107     if(l>=r) return null;
108     int m=l+r>>1;
109     Node* t=new Node();
110     Node* L=build(l,m),*R=build(m+1,r);
111     t->v=t->sum=t->lmax=t->rmax=t->mmax=a[m];
112     t->setc(L,0);
113     t->setc(R,1);
114     t->maintain();
115     return t;
116 }
117 void Insert(int pos,int tot)
118 {
119     if(!tot) return;
120     for(int i=0;i<tot;++i) scanf("%d",a+i);
121     Node* t=build(0,tot);
122     splay(select(pos));
123     splay(select(pos+1),root);
124     root->ch[1]->setc(t,0);
125     root->ch[1]->maintain();
126     root->maintain();
127 }
128 inline void Delete(int pos,int tot)
129 {
130     if(!tot) return;
131     Node*& t=get(pos,pos+tot);
132     DeleteTree(t);
133     root->ch[1]->maintain();
134     root->maintain();
135 }
136 inline void MakeSame(int pos,int tot,int c)
137 {
138     if(!tot) return;
139     Node*& t=get(pos,pos+tot);
140     t->MakeSame(c); 
141     t->p->maintain();
142     t->p->p->maintain();
143 }
144 inline void Reverse(int pos,int tot)
145 {
146     if(!tot || tot==1) return;
147     Node*& t=get(pos,pos+tot);
148     t->revIt();
149     t->p->maintain();
150     t->p->p->maintain();
151 }
152 inline int GetSum(int pos,int tot)
153 {
154     if(!tot) return 0;
155     Node*& t=get(pos,pos+tot);
156     return t->sum;
157 }
158 inline int MaxSum()
159 {
160     Node*& t=get(1,root->s-1);
161     return t->mmax;
162 }
163 int n,m;
164 char s[20];
165 int main()
166 {
167     //freopen("sequence.in","r",stdin);
168     //freopen("sequence.out","w",stdout);
169     scanf("%d%d",&n,&m);
170     for(int i=1;i<=n;++i) scanf("%d",a+i);
171     root=build(0,n+2);
172     root->p=null;
173     while(m--)
174     {
175         int pos,tot,c;
176         scanf("%s",s);
177         if(s[2]!='X') scanf("%d%d",&pos,&tot);
178         if(s[2]=='K') scanf("%d",&c);
179         switch(s[2])
180         {
181             case 'T':printf("%d\n",GetSum(pos,tot));
182                      break;
183             case 'S':Insert(pos,tot);
184                      break;
185             case 'V':Reverse(pos,tot);
186                      break;
187             case 'L':Delete(pos,tot);
188                      break;
189             case 'X':printf("%d\n",MaxSum());
190                      break;
191             case 'K':MakeSame(pos,tot,c);
192                      break;
193         }
194     }
195     return 0;
196 }
View Code
原文地址:https://www.cnblogs.com/lowsfish/p/4342473.html