bzoj 1500 维修数列

一道操作很多的splay的题目。

还是和原来一样, 减少代码量, 在最左边和最右边都添加一个新的虚节点。

每一个节点都维护 从左端点开始的最大连续子序列, 右端点开始的最大连续子序列, 可以不取, 即为0, 还要维护这段区间的最大值。

每次Update的时候更新数据。

每次翻转的时候, 要把这个点的 左端点开始的最大连续子序列, 右端点开始的最大连续子序列 先进行交换,因为这个会对答案产生影响, 所以对于翻转区间来说, 要更新第一个翻转区间, 再打lazy, 不能直接不更新, 打lazy。

还有就是 bzoj 开数组很花费时间, 所以要写一个函数来回收已经被删除掉的点。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define max3(a,b,c) max(a,max(b,c))
 12 #define min3(a,b,c) min(a,min(b,c))
 13 typedef pair<int,int> pll;
 14 const int inf = 0x3f3f3f3f;
 15 const LL INF = 0x3f3f3f3f3f3f3f3f;
 16 const LL mod =  (int)1e9+7;
 17 const int N = 5e5 + 100;
 18 int sta[N];
 19 int c[N];
 20 int top = 0, root;
 21 struct Node{
 22     int son[2], pre;
 23     int sz, val;
 24     int lf, rt, maxx, sum, ma;
 25     int lz1, lz2;
 26     void init(int m){
 27         sum = maxx = val = m;
 28         lf = rt = ma = max(0, m);
 29         son[0] = son[1] = pre = 0;
 30         sz = 1;
 31         lz1 = lz2 = 0;
 32     }
 33 }tr[N];
 34 void GG(int x, int v){
 35     if(!x) return ;
 36     tr[x].lz2 = 1;
 37     tr[x].val = tr[x].maxx = v;
 38     tr[x].sum = tr[x].sz * v;
 39     tr[x].lf = tr[x].rt = tr[x].ma = max(0, tr[x].sum);
 40 }
 41 void Push_Up(int x){
 42     if(!x) return ;
 43     int &l = tr[x].son[0], &r = tr[x].son[1];
 44     tr[x].sz = 1 + tr[l].sz + tr[r].sz;
 45     tr[x].sum = tr[l].sum + tr[r].sum + tr[x].val;
 46     tr[x].maxx = max3(tr[x].val, tr[l].maxx, tr[r].maxx);
 47     tr[x].lf = max(tr[l].lf, tr[l].sum + tr[r].lf + tr[x].val);
 48     tr[x].rt = max(tr[r].rt, tr[r].sum + tr[l].rt + tr[x].val);
 49     tr[x].ma = max3(tr[l].ma, tr[r].ma, tr[l].rt + tr[r].lf + tr[x].val);
 50 }
 51 void Push_Down(int x){
 52     if(!x) return ;
 53     int &l = tr[x].son[0], &r = tr[x].son[1];
 54     if(tr[x].lz1){
 55         tr[x].lz1 = 0;
 56         swap(l, r);
 57         swap(tr[l].lf, tr[l].rt);
 58         swap(tr[r].lf, tr[r].rt);
 59         tr[l].lz1 ^= 1;
 60         tr[r].lz1 ^= 1;
 61     }
 62     if(tr[x].lz2){
 63         tr[x].lz2 = 0;
 64         GG(l, tr[x].val);
 65         GG(r, tr[x].val);
 66     }
 67 }
 68 int build(int ll, int rr){
 69     if(ll > rr) return 0;
 70     int x = sta[top--];
 71     tr[x].init(c[ll]);
 72     tr[x].son[1] = build(ll+1, rr);
 73     tr[tr[x].son[1]].pre = x;
 74     Push_Up(x);
 75     return x;
 76 }
 77 char s[50];
 78 
 79 void rotate(int x){
 80     int y = tr[x].pre;
 81     int z = tr[y].pre;
 82     int k = tr[y].son[1] == x;
 83     tr[x].pre = z;
 84     tr[z].son[y == tr[z].son[1]] = x;
 85     tr[y].son[k] = tr[x].son[k^1];
 86     tr[tr[x].son[k^1]].pre = y;
 87     tr[y].pre = x;
 88     tr[x].son[k^1] = y;
 89     Push_Up(y);
 90 }
 91 void Splay(int x, int goal){
 92     Push_Down(x);
 93     while(tr[x].pre != goal){
 94         int y = tr[x].pre;
 95         int z = tr[y].pre;
 96         if(z != goal){
 97             if((tr[y].son[0] == x) ^ (tr[z].son[0] ==  y)) rotate(x);
 98             else rotate(y);
 99         }
100         rotate(x);
101     }
102     if(!goal) root = x;
103     Push_Up(x);
104 }
105 int Find(int x, int p){
106     Push_Down(p);
107     int &l = tr[p].son[0], &r = tr[p].son[1];
108     if(x == tr[l].sz + 1) return p;
109     if(x <= tr[l].sz) return Find(x, l);
110     return Find(x - tr[l].sz - 1, r);
111 }
112 void Insert(int l, int num){
113     int tt = build(1, num);
114     int pl = Find(l+1, root);
115     int pr = Find(l+2, root);
116     Splay(pr, 0);
117     Splay(pl, pr);
118     tr[pl].son[1] = tt;
119     tr[tt].pre = pl;
120     Push_Up(pl);
121     Push_Up(pr);
122 }
123 void Clear(int x){
124     if(tr[x].son[0]) Clear(tr[x].son[0]);
125     if(tr[x].son[1]) Clear(tr[x].son[1]);
126     sta[++top] = x;
127 }
128 void Delete(int l, int r){
129     int pl = Find(l, root);
130     int pr = Find(r+2, root);
131     Splay(pl, 0);
132     Splay(pr, pl);
133     Clear(tr[pr].son[0]);
134     tr[pr].son[0] = 0;
135     Push_Up(pr);
136     Push_Up(pl);
137 }
138 
139 void Make_same(int l, int r, int v){
140     int pl = Find(l, root);
141     int pr = Find(r+2, root);
142     Splay(pl, 0);
143     Splay(pr, pl);
144     GG(tr[pr].son[0], v);
145     int t = tr[pr].son[0];
146     Push_Up(pr);
147     Push_Up(pl);
148 }
149 void Reverse(int l, int r){
150     int pl = Find(l, root);
151     int pr = Find(r+2, root);
152     Splay(pl, 0);
153     Splay(pr, pl);
154     tr[tr[pr].son[0]].lz1 ^= 1;
155     Push_Down(tr[pr].son[0]);
156     Push_Up(tr[pr].son[0]);
157     Push_Up(pr);
158     Push_Up(pl);
159 }
160 int Get_sum(int l, int r){
161     int pl = Find(l, root);
162     int pr = Find(r+2, root);
163     Splay(pl, 0);
164     Splay(pr, pl);
165     return tr[tr[pr].son[0]].sum;
166 }
167 int Max_sum(){
168     if(tr[root].maxx < 0) return tr[root].maxx;
169     return tr[root].ma;
170 }
171 int main(){
172     for(int i = N-50; i > 0; i--) sta[++top] = i;
173     int n, m;
174     scanf("%d%d", &n, &m);
175     for(int i = 1; i <= n; i++) scanf("%d", &c[i]);
176     c[0] = c[n+1] = -inf;
177     tr[0].maxx = tr[0].val = -inf;
178     root = build(0, n+1);
179     int l, r, t;
180     while(m--){
181         scanf("%s", s);
182         if(s[0] == 'I'){
183             scanf("%d%d", &l, &r);
184             for(int i = 1; i <= r; i++) scanf("%d", &c[i]);
185             Insert(l,r);
186         }
187         else if(s[0] == 'D'){
188             scanf("%d%d", &l, &r);
189             Delete(l, l+r-1);
190         }
191         else if(s[2] == 'K'){
192             scanf("%d%d%d", &l, &r, &t);
193             Make_same(l, l+r-1, t);
194         }
195         else if(s[0] == 'R'){
196             scanf("%d%d", &l, &r);
197             Reverse(l, l+r-1);
198         }
199         else if(s[0] == 'G'){
200             scanf("%d%d", &l, &r);
201             printf("%d\n", Get_sum(l, l+r-1));
202         }
203         else {
204             printf("%d\n", Max_sum());
205         }
206     }
207     return 0;
208 }
View Code

 

posted @ 2018-08-10 09:57  Schenker  阅读(180)  评论(0编辑  收藏  举报