题目来源BZOJ1500

这题的思路:

1、这题的话,稍微会splay的人,一般前面四个都不是问题。。主要是最后的一个,要你在修改的同时要维护好最大字段和。。。

2、最大字段和其实就是区间合并。具体操作可以看POJ2750,这是这道题的简化版本。

3、然后这题就是三个区间合并嘛。。。慢慢讨论就好了。。。这题写了我一天的时间。。从吃完午饭一直写到了晚上8点才AC。。。

直接贴代码吧。。这题是我为了学LCT,所以想做做Splay的题先熟悉一下Splay。。。结果选了这个BOSS题。。。心理阴影。。。。

我觉得我pushup那段写的挺清楚的23333   思路可以看我的pushup和pushdown函数的代码,应该挺好懂的

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<stack>
  5.  
  6. using namespace std;
  7.  
  8. const int N=,INF=0x3f3f3f3f;
  9.  
  10. struct Splay_Tree
  11. {
  12. struct Node
  13. {
  14. int val,sum,cover,Size,son[],mxl,mxr,mx;
  15. bool rev,cov;
  16. void init(int _val)
  17. {
  18. val=sum=mxl=mxr=mx=_val;
  19. Size=;
  20. rev=cov=cover=son[]=son[]=;
  21. }
  22. } T[N];
  23. stack<int>mem;
  24. int fa[N],root,tot;
  25.  
  26. void pushDown(int x)///下放标记(序列操作)
  27. {
  28. if(x==)return ;
  29. if(T[x].cov)
  30. {
  31. if(T[x].son[])
  32. {
  33. T[T[x].son[]].cov=;
  34. T[T[x].son[]].cover=T[T[x].son[]].val=T[x].cover;
  35. T[T[x].son[]].sum=T[x].cover*T[T[x].son[]].Size;
  36. T[T[x].son[]].rev=;
  37. if(T[x].cover>=)
  38. T[T[x].son[]].mx=T[T[x].son[]].mxl=T[T[x].son[]].mxr=T[x].cover*T[T[x].son[]].Size;
  39. else
  40. T[T[x].son[]].mx=T[T[x].son[]].mxl=T[T[x].son[]].mxr=T[x].cover;
  41. }
  42. if(T[x].son[])
  43. {
  44. T[T[x].son[]].cov=;
  45. T[T[x].son[]].cover=T[T[x].son[]].val=T[x].cover;
  46. T[T[x].son[]].sum=T[x].cover*T[T[x].son[]].Size;
  47. T[T[x].son[]].rev=;
  48. if(T[x].cover>=)
  49. T[T[x].son[]].mx=T[T[x].son[]].mxl=T[T[x].son[]].mxr=T[x].cover*T[T[x].son[]].Size;
  50. else
  51. T[T[x].son[]].mx=T[T[x].son[]].mxl=T[T[x].son[]].mxr=T[x].cover;
  52. }
  53. T[x].cov=T[x].cover=T[x].rev=;
  54. }
  55. if(T[x].rev)
  56. {
  57. if(T[x].son[])
  58. {
  59. T[T[x].son[]].rev^=;
  60. swap(T[T[x].son[]].mxl,T[T[x].son[]].mxr);
  61. }
  62. if(T[x].son[])
  63. {
  64. T[T[x].son[]].rev^=;
  65. swap(T[T[x].son[]].mxl,T[T[x].son[]].mxr);
  66. }
  67. swap(T[x].son[],T[x].son[]);
  68. T[x].rev=;
  69. }
  70. }
  71.  
  72. void pushUp(int x)///更新节点(序列操作)
  73. {
  74. T[x].Size=;
  75. T[x].sum=T[x].val;
  76. if(T[x].son[])
  77. T[x].sum+=T[T[x].son[]].sum,T[x].Size+=T[T[x].son[]].Size;
  78. if(T[x].son[])
  79. T[x].sum+=T[T[x].son[]].sum,T[x].Size+=T[T[x].son[]].Size;
  80.  
  81. if(T[x].son[]&&T[x].son[])
  82. {
  83. T[x].mx=T[x].val;
  84. T[x].mx=max(T[x].mx,T[T[x].son[]].mx);
  85. T[x].mx=max(T[x].mx,T[T[x].son[]].mx);
  86. T[x].mx=max(T[x].mx,T[T[x].son[]].mxr+T[x].val+T[T[x].son[]].mxl);
  87. T[x].mx=max(T[x].mx,T[x].val+T[T[x].son[]].mxr);
  88. T[x].mx=max(T[x].mx,T[x].val+T[T[x].son[]].mxl);
  89.  
  90. T[x].mxl=T[T[x].son[]].mxl;
  91. T[x].mxl=max(T[x].mxl,T[T[x].son[]].sum+T[x].val);
  92. T[x].mxl=max(T[x].mxl,T[T[x].son[]].sum+T[x].val+T[T[x].son[]].mxl);
  93.  
  94. T[x].mxr=T[T[x].son[]].mxr;
  95. T[x].mxr=max(T[x].mxr,T[T[x].son[]].sum+T[x].val);
  96. T[x].mxr=max(T[x].mxr,T[T[x].son[]].sum+T[x].val+T[T[x].son[]].mxr);
  97. }
  98. else if(T[x].son[]&&!T[x].son[])
  99. {
  100. T[x].mx=max(T[T[x].son[]].mxr+T[x].val,T[T[x].son[]].mx);
  101.  
  102. T[x].mx=max(T[x].mx,T[x].val);
  103.  
  104. T[x].mxl=max(T[T[x].son[]].mxl,T[T[x].son[]].sum+T[x].val);
  105.  
  106. T[x].mxr=max(T[x].val,T[x].val+T[T[x].son[]].mxr);
  107. }
  108. else if(!T[x].son[]&&T[x].son[])
  109. {
  110. T[x].mx=max(T[T[x].son[]].mxl+T[x].val,T[T[x].son[]].mx);
  111.  
  112. T[x].mx=max(T[x].mx,T[x].val);
  113.  
  114. T[x].mxl=max(T[x].val,T[x].val+T[T[x].son[]].mxl);
  115.  
  116. T[x].mxr=max(T[T[x].son[]].mxr,T[T[x].son[]].sum+T[x].val);
  117. }
  118. else T[x].mxl=T[x].mxr=T[x].mx=T[x].val;
  119.  
  120. }
  121.  
  122. /*inline void up(int x)///更新节点(普通平衡树操作)
  123. {
  124. T[x].Size=1;
  125. if(T[x].son[0])
  126. T[x].Size+=T[T[x].son[0]].Size;
  127. if(T[x].son[1])
  128. T[x].Size+=T[T[x].son[1]].Size;
  129. }*/
  130.  
  131. void Rotate(int x,int kind)///旋转,有左旋右旋(反正配合splay用就好了233)
  132. {
  133. int y=fa[x],z=fa[y];
  134. T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;
  135. T[x].son[kind]=y,fa[y]=x;
  136. T[z].son[T[z].son[]==y]=x,fa[x]=z;
  137. pushUp(y);
  138. }
  139.  
  140. void Splay(int x,int goal)///把下标为x的元素旋转到目标的儿子节点
  141. {
  142. if(x==goal)return ;
  143. while(fa[x]!=goal)
  144. {
  145. int y=fa[x],z=fa[y];
  146. pushDown(z),pushDown(y),pushDown(x);
  147. int rx=T[y].son[]==x,ry=T[z].son[]==y;
  148. if(z==goal)Rotate(x,rx);
  149. else
  150. {
  151. if(rx==ry)Rotate(y,ry);
  152. else Rotate(x,rx);
  153. Rotate(x,ry);
  154. }
  155. }
  156. pushUp(x);
  157. if(goal==)root=x;
  158. }
  159.  
  160. int Select(int pos)///查找第k小元素
  161. {
  162. pos--;
  163. int u=root;
  164. pushDown(u);
  165. while(T[T[u].son[]].Size!=pos)
  166. {
  167. if(pos<T[T[u].son[]].Size)u=T[u].son[];
  168. else
  169. {
  170. pos-=T[T[u].son[]].Size+;
  171. u=T[u].son[];
  172. }
  173. pushDown(u);
  174. }
  175. return u;
  176. }
  177.  
  178. void Reverse(int L,int R)///序列操作的区间翻转
  179. {
  180. if(L>R)return ;
  181. int u=Select(L-),v=Select(R+);
  182. Splay(u,);
  183. Splay(v,u);
  184. T[T[v].son[]].rev^=;
  185. swap(T[T[v].son[]].mxl,T[T[v].son[]].mxr);
  186. pushDown(T[v].son[]);
  187. update(T[v].son[]);
  188. }
  189.  
  190. void Cover(int L,int R,int Val)///序列操作的区间翻转
  191. {
  192. if(L>R)return ;
  193. int u=Select(L-),v=Select(R+);
  194. Splay(u,);
  195. Splay(v,u);
  196. T[T[v].son[]].cov=;
  197. T[T[v].son[]].cover=T[T[v].son[]].val=Val;
  198. pushDown(T[v].son[]);
  199. update(T[v].son[]);
  200. }
  201.  
  202. int build(int L,int R,int *a)///区间操作建树
  203. {
  204. if(L>R)return ;
  205. int mid=(L+R)>>,sL,sR;
  206. int loc=mem.top();mem.pop();
  207. T[loc].init(a[mid]);
  208. if(L==R)return loc;
  209. T[loc].son[]=sL=build(L,mid-,a);
  210. T[loc].son[]=sR=build(mid+,R,a);
  211. fa[sL]=fa[sR]=loc;
  212. pushUp(loc);
  213. return loc;
  214. }
  215.  
  216. void init(int n,int *a)///区间操作,输入n个元素建树
  217. {
  218. T[].init(INF);
  219. for(int i=;i>=;i--)
  220. mem.push(i);
  221. root=build(,n,a),fa[root]=;
  222. fa[]=,T[].son[]=root,T[].Size=;
  223. }
  224.  
  225. void Insert(int pos,int n,int *a)
  226. {
  227. if(n==)return ;
  228. int u=Select(pos-),v=Select(pos);
  229. Splay(u,);
  230. Splay(v,u);
  231. fa[T[v].son[]=build(,n,a)]=v;
  232. update(T[v].son[]);
  233. }
  234.  
  235. void Delete(int L,int R)
  236. {
  237. if(L>R)return ;
  238. int u=Select(L-),v=Select(R+);
  239. Splay(u,);
  240. Splay(v,u);
  241. Free(T[v].son[]);
  242. T[v].son[]=;
  243. update(v);
  244. }
  245.  
  246. int Get_sum(int L,int R)
  247. {
  248. if(L>R)return ;
  249. int u=Select(L-),v=Select(R+);
  250. Splay(u,);
  251. Splay(v,u);
  252. if(T[v].son[])
  253. return T[T[v].son[]].sum;
  254. else return ;
  255. }
  256.  
  257. int Get_max(int L,int R)
  258. {
  259. if(L>R)return ;
  260. int u=Select(L-),v=Select(R+);
  261. Splay(u,);
  262. Splay(v,u);
  263. if(T[v].son[])
  264. return T[T[v].son[]].mx;
  265. else return ;
  266. }
  267.  
  268. void Free(int x)
  269. {
  270. if(x==)return ;
  271. Free(T[x].son[]);
  272. mem.push(x);
  273. Free(T[x].son[]);
  274. }
  275.  
  276. /*void Insert(int &t,int val,int par=0)///普通平衡树,往某个地方的下面插入元素,一般是插入根节点
  277. {
  278. if(t==0)
  279. {
  280. t=++tot;
  281. T[t].init(val);
  282. fa[t]=par;
  283. Splay(tot,0);
  284. }
  285. else
  286. {
  287. int cur=t;
  288. if(val<T[t].val)Insert(T[t].son[0],val,cur);
  289. //else if(val==T[t].val)return ;
  290. else Insert(T[t].son[1],val,cur);
  291. up(cur);
  292. }
  293. }*/
  294.  
  295. /*int find(int t,int v)///普通平衡树查找值为v的元素
  296. {
  297. if(t==0)return 0;
  298. else if(T[t].val==v)
  299. {
  300. Splay(t,0);
  301. return t;
  302. }
  303. else if(v<T[t].val)return find(T[t].son[0],v);
  304. else return find(T[t].son[1],v);
  305. }*/
  306.  
  307. ///删除根节点元素
  308. /*void Delete()
  309. {
  310. if(!T[root].son[0])
  311. {
  312. fa[T[root].son[1]]=0;
  313. root=T[root].son[1];
  314. }
  315. else
  316. {
  317. int cur=T[root].son[0];
  318. while(T[cur].son[1])cur=T[cur].son[1];
  319. Splay(cur,root);
  320. T[cur].son[1]=T[root].son[1];
  321. root=cur,fa[cur]=0,fa[T[root].son[1]]=root;
  322. up(root);
  323. }
  324. }*/
  325.  
  326. int size()
  327. {
  328. return T[root].Size;
  329. }
  330.  
  331. ///从t开始找值为v的前驱,返回值
  332. int pred(int t,int v)
  333. {
  334. if(t==)return v;
  335. else
  336. {
  337. if(v<=T[t].val)return pred(T[t].son[],v);
  338. else
  339. {
  340. int ans=pred(T[t].son[],v);
  341. if(ans==v)
  342. ans=T[t].val,Splay(t,);
  343. return ans;
  344. }
  345. }
  346. }
  347. ///查找下标t节点的前驱返回下标
  348. int pred(int t)
  349. {
  350. Splay(t,);
  351. int u=T[t].son[];
  352. if(u==)return fa[t];
  353. while(T[u].son[])u=T[u].son[];
  354. return u;
  355. }
  356.  
  357. ///从t开始找值为v的后继,返回值
  358. int succ(int t,int v)
  359. {
  360. if(t==)return v;
  361. else
  362. {
  363. if(v>=T[t].val)return succ(T[t].son[],v);
  364. else
  365. {
  366. int ans=succ(T[t].son[],v);
  367. if(ans==v)
  368. ans=T[t].val,Splay(t,);
  369. return ans;
  370. }
  371. }
  372. }
  373.  
  374. ///查找下标t节点的后继返回下标
  375. int succ(int t)
  376. {
  377. Splay(t,);
  378. int u=T[t].son[];
  379. if(u==)return fa[t];
  380. while(T[u].son[])u=T[u].son[];
  381. return u;
  382. }
  383.  
  384. void Preorder( int t ){///输出成序列顺便检查是否有逻辑错误
  385. if( !t ) return;
  386. pushDown(t);
  387. Preorder( T[t].son[] );
  388. if(T[t].son[]&&fa[T[t].son[]]!=t)
  389. printf("!");
  390. printf("%d " , T[t].val );
  391. Preorder( T[t].son[] );
  392. }
  393.  
  394. /*void init()///普通平衡树初始化
  395. {
  396. T[0].init(-INF);
  397. tot=root=0;
  398. }*/
  399.  
  400. void update(int x)///更新下标为x的节点。。手动操作后调用
  401. {
  402. while(x!=)
  403. pushUp(x),x=fa[x];
  404. }
  405.  
  406. };
  407.  
  408. Splay_Tree tree;
  409.  
  410. int a[N];
  411.  
  412. char str[];
  413.  
  414. int main()
  415. {
  416. int n,m;
  417. scanf("%d%d",&n,&m);
  418. for(int i=;i<=n+;i++)
  419. scanf("%d",a+i);
  420. tree.init(n+,a);
  421. int sum=n;
  422. while(m--)
  423. {
  424. scanf("%s",str+);
  425. if(str[]=='S')
  426. {
  427. int pos,tot;
  428. scanf("%d%d",&pos,&tot);
  429. pos++;
  430. pos++;
  431. sum+=tot;
  432. for(int i=;i<=tot;i++)
  433. scanf("%d",a+i);
  434. tree.Insert(pos,tot,a);
  435. }
  436. else if(str[]=='L')
  437. {
  438. int pos,tot;
  439. scanf("%d%d",&pos,&tot);
  440. pos++;
  441. tree.Delete(pos,pos+tot-);
  442. sum-=tot;
  443. }
  444. else if(str[]=='K')
  445. {
  446. int pos,tot,cov;
  447. scanf("%d%d%d",&pos,&tot,&cov);
  448. pos++;
  449. tree.Cover(pos,pos+tot-,cov);
  450. }
  451. else if(str[]=='V')
  452. {
  453. int pos,tot;
  454. scanf("%d%d",&pos,&tot);
  455. pos++;
  456. tree.Reverse(pos,pos+tot-);
  457. }
  458. else if(str[]=='T')
  459. {
  460. int pos,tot;
  461. scanf("%d%d",&pos,&tot);
  462. pos++;
  463. printf("%d\n",tree.Get_sum(pos,pos+tot-));
  464. }
  465. if(str[]=='X')
  466. {
  467. printf("%d\n",tree.Get_max(,tree.size()-));
  468. }
  469. }
  470. return ;
  471. }

维修数列 Splay(这可能是我写过最麻烦的题之一了。。。用平衡树维护dp。。。丧心病狂啊。。。。)的更多相关文章

  1. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  2. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  3. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  4. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

  5. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

  6. BZOJ1500: [NOI2005]维修数列[splay ***]

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12278  Solved: 3880[Submit][Statu ...

  7. BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】

    以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...

  8. BZOJ1500 [NOI2005]维修数列(Splay tree)

    [Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 Inp ...

  9. bzoj1500: [NOI2005]维修数列 (Splay+变态题)

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11353  Solved: 3553 [Submit][Status][Discuss] Descrip ...

随机推荐

  1. 菜鸟初学redis(二)

    如果你的redis可以在myeclipse上运行小demo了,那么可以继续学习了 redis Java String 实例 string是redis最基本的类型,一个key对应一个value. str ...

  2. phpcms公共函数库 总结

    *  global.func.php 公共函数库 /** * 返回经addslashes处理过的字符串或数组 * @param $string 需要处理的字符串或数组 * @return mixed ...

  3. flutter- 圆角

    单个圆角变化 Container( height: 200, decoration: BoxDecoration( color: Colors.green, borderRadius: BorderR ...

  4. php 随机红包算法

    <?php /** * 红包分配算法 * * example * $coupon = new Coupon(200, 5); * $res = $coupon->handle(); * p ...

  5. 题解 Luogu P3623 [APIO2008]免费道路

    [APIO2008]免费道路 题目描述 新亚(New Asia)王国有 N 个村庄,由 M 条道路连接.其中一些道路是鹅卵石路,而其它道路是水泥路.保持道路免费运行需要一大笔费用,并且看上去 王国不可 ...

  6. [Python数据挖掘]第2章、Python数据分析简介

    <Python数据分析与挖掘实战>的数据和代码,可从“泰迪杯”竞赛网站(http://www.tipdm.org/tj/661.jhtml)下载获得 1.Python数据结构 2.Nump ...

  7. linux系统ansible一键完成三大服务器基本配置

    准备: 五台服务器:一台管理服务器m01:172.16.1.61.两台应用服务器web01:172.16.1.7.web02:172.16.1.8.一台存储服务器nfs:172.16.1.31.一台备 ...

  8. IDEA上的项目托管到码云步骤

    IDEA上的项目托管到码云步骤:1.安装Git2.idea上配置Git    Setting-Version Control-Git    把git.exe改为安装的Git的执行路径如:D:\Prog ...

  9. zabbix触发器表达式

    zabbix触发器表达式 触发器使用逻辑表达式来评估通过item获取的数据是处于哪种状态, 触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下: {<serve ...

  10. 數據監控与診斷--環形緩沖區(RING BUFFER)

    1.  環形緩沖區 動態管理視圖: sys.dm_os_ring_buffers 查看ring_buffers: Select distinct ring_buffer_type from sys.d ...