HDU5773-The All-purpose Zero-多校#41010-最长上升子序列问题

只想到了朴素的n^2做法,然后发现可以用splay维护。于是调了几个小时的splay。。。

splay的元素是从第二个开始的!第一个是之前插入的头节点!

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4
  5 using namespace std;
  6
  7 #define Key_value ch[ch[root][1] ][0]
  8
  9 const int maxn = 5e5+10;
 10 const int INF = 0x3f3f3f3f;
 11
 12 int pre[maxn],ch[maxn][2],key[maxn],sz[maxn];
 13 int root,tot1;
 14 int rev[maxn],ma[maxn],add[maxn];
 15 int s[maxn],tot2;
 16 int a[maxn];
 17 //int n,q;
 18
 19 void Treavel(int x)
 20 {
 21     if(x)
 22     {
 23         Treavel(ch[x][0]);
 24         printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d key=%2d size= %2d ma=%2d add=%2d\n",x,ch[x][0],ch[x][1],pre[x],key[x],sz[x],ma[x],add[x]);
 25         Treavel(ch[x][1]);
 26     }
 27 }
 28 void debug()
 29 {
 30     printf("root:%d\n",root);
 31     Treavel(root);
 32 }
 33 //
 34
 35 void NewNode(int &r,int father,int k)
 36 {
 37     if(tot2) r = s[tot2--];
 38     else r = ++tot1;
 39     pre[r] = father;
 40     ch[r][0] = ch[r][1] = 0;
 41     key[r] = k;
 42     ma[r] = k;
 43     rev[r] = add[r] = 0;
 44     sz[r] = 1;
 45 }
 46
 47 void Update_add(int r,int c)
 48 {
 49     if(!r) return ;
 50     key[r] += c;
 51     ma[r] += c;
 52     add[r] += c;
 53 }
 54
 55 void Update_rev(int r)
 56 {
 57     if(!r) return ;
 58     swap(ch[r][0],ch[r][1]);
 59     rev[r] ^= 1;
 60 }
 61
 62 void push_up(int r)
 63 {
 64     int lson = ch[r][0],rson = ch[r][1];
 65     sz[r] = sz[lson] + sz[rson] + 1;
 66     //ma[r] = max(max(ma[lson],ma[rson]),key[r]);
 67     ma[r] = max(max(ma[lson],ma[rson]),key[r]);
 68 }
 69 void update_same(int r,int c)
 70 {
 71     if(!r) return ;
 72     int lson = ch[r][0],rson = ch[r][1];
 73     key[r] = c;
 74     //ma[r] = max(max(ma[lson],ma[rson]),c);
 75     ma[r] = c;
 76 }
 77 void push_down(int r)
 78 {
 79     if(rev[r])
 80     {
 81         Update_rev(ch[r][0]);
 82         Update_rev(ch[r][1]);
 83         rev[r] = 0;
 84     }
 85     if(add[r])
 86     {
 87         Update_add(ch[r][0],add[r]);
 88         Update_add(ch[r][1],add[r]);
 89         add[r] = 0;
 90     }
 91 }
 92
 93 void Build(int &x,int l,int r,int father)
 94 {
 95     if(l>r) return ;
 96     int mid = (l+r)>>1;
 97     NewNode(x,father,a[mid]);
 98     Build(ch[x][0],l,mid-1,x);
 99     Build(ch[x][1],mid+1,r,x);
100     push_up(x);
101 }
102
103 void Init(int x)
104 {
105     root = tot1 = tot2 = 0;
106     ch[root][0] = ch[root][1] = sz[root] = pre[root] = 0;
107     rev[root] = key[root] = 0;
108     ma[root] = 0;
109     NewNode(root,0,-1);
110     NewNode(ch[root][1],root,-1);
111     //for(int i=1;i<=n;i++) scanf("%d",&a[i]);
112     a[1] = x;
113     //n = 1;
114     Build(Key_value,1,1,ch[root][1]);
115     push_up(ch[root][1]);
116     push_up(root);
117 }
118
119 void Rotate(int x,int kind)
120 {
121     int y = pre[x];
122     push_down(y);
123     push_down(x);
124     ch[y][!kind] = ch[x][kind];
125     pre[ch[x][kind] ] = y;
126     if(pre[y])
127         ch[pre[y] ][ch[pre[y]][1]==y ] = x;
128     pre[x] = pre[y];
129     ch[x][kind] = y;
130     pre[y] = x;
131     push_up(y);
132 }
133 void Splay(int r,int goal)
134 {
135     push_down(r);
136     while(pre[r] != goal)
137     {
138         if(pre[pre[r] ] == goal)
139         {
140             push_down(pre[r]);
141             push_down(r);
142             Rotate(r,ch[pre[r]][0] == r);
143         }
144         else
145         {
146             push_down(pre[pre[r] ]);
147             push_down(pre[r]);
148             push_down(r);
149             int y = pre[r];
150             int kind = ch[pre[y] ][0] == y;
151             if(ch[y][kind] == r)
152             {
153                 Rotate(r,!kind);
154                 Rotate(r,kind);
155             }
156             else
157             {
158                 Rotate(y,kind);
159                 Rotate(r,kind);
160             }
161         }
162         push_up(r);
163         if(goal == 0) root = r;
164     }
165 }
166
167 int Get_kth(int r,int k)
168 {
169     push_down(r);
170     int t = sz[ch[r][0] ] + 1;
171     if(t == k) return r;
172     if(t > k) return Get_kth(ch[r][0],k);
173     else return Get_kth(ch[r][1],k-t);
174 }
175
176 void Insert(int pos,int x)
177 {
178     //for(int i=0;i<tot;i++) scanf("%d",&a[i]);
179     int tot = 1;
180     a[0] = x;
181     Splay(Get_kth(root,pos) , 0);
182     Splay(Get_kth(root,pos+1) , root);
183     Build(Key_value,0,tot-1,ch[root][1]);
184     push_up(ch[root][1]);
185     push_up(root);
186 }
187 void erase(int r)
188 {
189     if(!r) return ;
190     s[++tot2] = r;
191     erase(ch[r][0]);
192     erase(ch[r][1]);
193 }
194 void Delete(int pos,int tot)
195 {
196     Splay(Get_kth(root,pos) ,0);
197     Splay(Get_kth(root,pos+tot+1) , root);
198     erase(Key_value);
199     pre[Key_value] = 0;
200     Key_value = 0;
201     push_up(ch[root][1]);
202     push_up(root);
203 }
204
205 void Reverse(int pos,int tot)
206 {
207     Splay(Get_kth(root,pos) , 0);
208     Splay(Get_kth(root,pos+tot+1), root);
209     Update_rev(Key_value);
210 }
211
212 void Add(int pos,int tot,int c)
213 {
214     Splay(Get_kth(root,pos) , 0);
215     Splay(Get_kth(root,pos+tot+1) , root);
216     Update_add(Key_value,c);
217     push_up(ch[root][1]);
218     push_up(root);
219 }
220 void Make_same(int pos,int tot,int c)
221 {
222     Splay(Get_kth(root,pos) , 0);
223     Splay(Get_kth(root,pos+tot+1) , root);
224     //printf("tihuan\n");
225     //debug();
226     update_same(Key_value,c);
227     push_up(ch[root][1]);
228     push_up(root);
229 }
230 int Get_max(int pos,int tot)
231 {
232     Splay(Get_kth(root,pos) , 0);
233     Splay(Get_kth(root,pos+tot+1) , root);
234     push_down(root);
235     push_down(ch[root][1]);
236     return ma[Key_value];
237 }
238 int Get_final_ans(int pos,int tot,int x)
239 {
240     int low = pos+1,high = pos+tot-1;
241     int mid;
242     while(low <= high)
243     {
244         mid = (low+high)>>1;
245         int b = key[Get_kth(root,mid)];
246         //printf("mid:%d k:%d\n",mid,b);
247         if(x >= b) low = mid+1;
248         else high = mid -1;
249     }
250     //printf("l:%d h:%d m:%d\n",low,high,mid);
251     return (low+high)>>1;
252 }
253
254 void Revolve(int l,int r,int t)
255 {
256     if(!t) return ;
257     int c = r - t;
258     Splay(Get_kth(root,l) , 0);
259     Splay(Get_kth(root,c+2),root);
260     int tmp = Key_value;
261     Key_value = 0;
262     push_up(ch[root][1]);
263     push_up(root);
264     Splay(Get_kth(root,r-c+l) , 0);
265     Splay(Get_kth(root,r-c+l+1) , root);
266     Key_value = tmp;
267     pre[Key_value] = ch[root][1];
268     push_up(ch[root][1]);
269     push_up(root);
270 }
271
272 int save[maxn];
273 int T,N;
274 int LL,RR;
275 int DP(int l,int n)
276 {
277     if(n==0) return 0;
278     int i,len=1,pos;
279     Init(save[l]);
280     //debug();
281     //printf("---\n");
282     for(int i=l+1;i<=n;i++)
283     {
284         //printf("save:%d len:%d max:%d\n",save[i],len,Get_max(1,len));
285         if(save[i] == 0)
286         {
287             Add(1,len,1);
288             Insert(1,0);
289             len++;
290         }
291         else if(save[i] > Get_max(1,len))
292         {
293             //printf("max:%d\n",Get_max(1,len));
294             Insert(len+1,save[i]);
295             len++;
296         }
297         else{
298             pos = Get_final_ans(1,len,save[i]);
299             //printf("pos:%d\n",pos);
300             //Add(pos,1,save[i]-key[Get_kth(root,pos)]);
301             Make_same(pos,1,save[i]);
302         }
303
304         //debug();
305         //printf("---\n");
306     }
307     return len;
308 }
309 bool flag = false;
310 void deal()
311 {
312     int i = 1;
313     while( save[i]==0 && i <= N) i++;
314     LL = i;
315     i = N;
316     if(LL>=N ) {flag = true;return;}
317     while(save[i] == 0 && i >= 0) i--;
318     RR = i;
319 }
320 int main()
321 {
322     //freopen("input","r",stdin);
323     //freopen("splay.out","w",stdout);
324     scanf("%d",&T);
325     for(int cas=1;cas<=T;cas++)
326     {
327         scanf("%d",&N);
328         for(int i=1;i<=N;i++)
329         {
330             scanf("%d",&save[i]);
331         }
332         flag = false;
333         deal();
334         if(flag){
335             printf("Case #%d: %d\n",cas,N);
336             continue;
337         }
338         //printf("LL:%d RR:%d\n",LL,RR);
339         int ans = DP(LL,RR);
340         printf("Case #%d: %d\n",cas,ans+LL-1+(N-RR));
341     }
342 }
343 /*
344 int m;
345 int main()
346 {
347     while(~scanf("%d ",&n))
348     {
349         Init();
350         //debug();
351         scanf("%d ",&m);
352         char op[10];
353         for(int i=0;i<m;i++)
354         {
355             scanf(" %s",op);
356             //printf("i:%d op:%s\n",i,op);
357             int x,y,c,t;
358             if(op[0] == ‘A‘)            //add
359             {
360                 scanf("%d%d%d",&x,&y,&c);
361                 Add(x,y-x+1,c);
362             }
363             else if(op[0] == ‘I‘)       //insert
364             {
365                 scanf("%d",&x);
366                 Insert(x,1);
367             }
368             else if(op[0] == ‘D‘)       //delete
369             {
370                 scanf("%d",&x);
371                 Delete(x,1);
372             }
373             else if(op[0] == ‘M‘)       //min
374             {
375                 scanf("%d%d",&x,&y);
376                 printf("%d\n",Get_min(x,y-x+1));
377             }
378             else if(op[0] == ‘R‘ && op[3] == ‘E‘)//reverse
379             {
380                 scanf("%d%d",&x,&y);
381                 Reverse(x,y-x+1);
382             }
383             else                        //revolve
384             {
385                 scanf("%d%d%d",&x,&y,&t);
386                 t = (t%(y-x+1)+(y-x+1))%(y-x+1);
387                 Revolve(x,y,t);
388             }
389             //debug();
390         }
391     }
392 }
393 */
时间: 2024-10-12 11:59:30

HDU5773-The All-purpose Zero-多校#41010-最长上升子序列问题的相关文章

hdu5773 最长上升子序列变形(附带模板)

先说说最长上升子序列的模板,时间复杂度O(nlogn) 最长上升子序列 #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N = 41000; int a[N],p; //a[i] 原始数据 int d[N]; //d[i] 长度为i的递增子序列的最小值 int BinSearch(int key, int low, int high)//二分查

蒟蒻ACMer回忆录 &#183; 一段弱校ACM的奋斗史

三年半的ACM生涯终于迎来了终点,退役之时,感慨万分,故写此文以纪念逝去的时光,那些为ACM拼搏的日子,那段弱校ACM的奋斗史. 三年半的ACM生涯,窝见证了CUMT从打铁到铜牌的突破,又见证了从铜牌到银牌的突破:见证了集训队员从3人发展到10余人,又见证了ACM实验室的落实. 三年半的ACM生涯,窝经历了太多,有Accepted时的欢笑,有Wrong Answer时的沮丧,有Time Limit Exceeded时的无奈,有Runtime Error时的尴尬,有打铁的失落,有拿牌的惊喜. 13

校赛总结

写写校赛总结....... 这两次校赛是我们组队以后第一次的比赛...第一场打得很拙,第二场还可以吧,第一场校赛--毕竟是期待了很久的校赛,所以感觉还是很紧张,吃饭的时候打了二两,剩了一大半==, 这次我们队名叫 I_Love_High_Math......没走到现场,就快下雨了,真的有点郁闷==.到了以后下雨了,和一个队友被困雨中,,出来以后衣服湿了,一开始就悲剧了...     然后一开场就感觉不好.比赛开始的时候,我去写头文件,然后W说A是水题,然后叫我写,平时都是我写第一题的这次我不想开

2014哈商大ICPC/ACM校赛解题报告

被debug邀请去參加校赛,哎,被虐..我对不起工大.. 由于本人不搞ACM,算法处于HelloWorld水准.. 虽然题目除了鸟不拉屎星人之外都非常水,但我能做到这个程度,全然是超水平发挥了.. 数据:点此下载 ============================================================== a:逆序数组+删除特定元素 题目: 小伙伴们好像非常多没接触过ICPC,那先来一道水题尝尝鲜,给出 一个数组,和一个特征值.将这个数组中特征值值删除后逆序输出.

2015 GDUT校赛

周末打了个GDUT的校赛,也是作为SCAU的一场个人排位. 比赛中竟然卡了个特判,1个半钟就切了5条了,然后一直卡. 还有其他两条可以做的题也没法做了,性格太执着对ACM来说也是错呀. 讲回正题 . A  游戏王 . 目的是集齐6张卡, 然后n个小伙伴手上持有卡num, 给出m种集合 , Stubird需要有某个集合中的卡片才能用c的花费去买这张卡片. 做法是状压dp , 开一个 dp[st] , 表示st( 0 <= st < (1<<6) ) 这个集合最小花费 . 然后开一个邻

Dynamic Programming | Set 3 (Longest Increasing Subsequence)

在 Dynamic Programming | Set 1 (Overlapping Subproblems Property) 和 Dynamic Programming | Set 2 (Optimal Substructure Property) 中我们已经讨论了重叠子问题和最优子结构性质,现在我们来看一个可以使用动态规划来解决的问题:最长上升子序列(Longest Increasing Subsequence(LIS)). 最长上升子序列问题,致力于在一个给定的序列中找到一个最长的子序列

luanqibazao

#include <iostream> #include <stdio.h> #include <vector> #include <algorithm> //组合数模板 /* int C(int n, int r) { int sum = 1; for (int i = 1; i <= r; i++) { sum = sum * (n + 1 - i) / i; } return sum; } */ //---------------- //将字符串

剪辑的楼天城的ACM之路

楼天城楼教主的acm心路历程(剪辑) 利用假期空闲之时,将这几年GCJ,ACM,TopCoder 参加的一些重要比赛作个回顾.昨天是GCJ2006 的回忆,今天时间上更早一些吧,我现在还清晰记得3 年前,我刚刚参加ACM 时参加北京赛区2005 和杭州赛区2005 的情况.2005 年ACM-ICPC——酸甜苦辣我进入清华大学开始本科学习的时间是2004 年8 月,在进入清华大学的第一年里,由于基础课学习比较紧张,再加上计算机系不允许大一学生自带电脑,我没有参加2004 年的ACM 比赛.不过在

微软等数据结构+算法面试100题全部答案集锦

1.把二元查找树转变成排序的双向链表. 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. 要求不能创建任何新的结点,只调整指针的指向. 10  / \  6 14  / \ / \  4 8 12 16 转换成双向链表 4=6=8=10=12=14=16. 首先我们定义的二元查找树节点的数据结构如下: struct BSTreeNode  {  int m_nValue; // value of node  BSTreeNode *m_pLeft; // left child