经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C » 查看文章
珂朵莉树(Chtholly Tree)学习笔记
来源:cnblogs  作者:shremier  时间:2018/11/6 10:17:50  对本文有异议

珂朵莉树(Chtholly Tree)学习笔记


珂朵莉树原理

其原理在于运用一颗树(set,treap,splay......)其中要求所有元素有序,并且支持基本的操作(删除,添加,查找......)来实现区间压缩。

那么区间压缩的意义在于区间推平这是珂朵莉树的核心(如果没有这个操作实际上不一定需要这种算法)

ps:若保证有连续相等甚至递增的区间,也可以的(吧?)。

可想而知它的操作在于对区间的分裂合并操作

(为什么?因为这样可以方便而快捷的区间推平

珂朵莉树的实现

在众多树中因为set这个c++自带,所以决定选择它。

结构

一个node结构体——把它叫区间(已typedef long long LL)

  1. struct node
  2. {
  3. int l,r;LL v;//这里官方写法加了一个mutable,看个人写法
  4. node(int L,int R,LL V):l(L),r(R),v(V){}
  5. bool operator < (const node& o) const
  6. {
  7. return l<o.l;
  8. }
  9. };

声明集合

  1. set<node>s;

初始化

  1. for(int i=1;i<=n;++i)
  2. s.insert(i,i,val);
  3. s.insert(n+1,n+1,0);//见下面中it!=s.end()的前提

分裂

  1. #define it_ set<node>::iterator
  2. it_ split(int pos)
  3. {
  4. it_ it=s.lower_bound(node(pos));
  5. if(it!=s.end()&& it->l==pos) return it;
  6. --it;
  7. int ll=it->l,rr=it->r;
  8. LL vv=it->v;
  9. s.erase(it);
  10. s.insert(node(ll,pos-1,vv));
  11. return s.insert(node(pos,rr,vv)).first;
  12. }

区间推平

  1. void assign(int l,int r,LL val=0)
  2. {
  3. it_ itl=split(l),itr=split(r+1);
  4. s.erase(itl,itr);
  5. s.insert(node(l,r,val));
  6. }

如上。


例子

见cf896c

仅仅给出代码

  1. #include <bits/stdc++.h>
  2. #define it_ set<node>::iterator
  3. // #define swap(X,Y) {int (tmp)=(X),(X)=(Y),(Y)=(tmp);}
  4. using namespace std;
  5. typedef long long LL;
  6. const int M7=1e9+7;
  7. const int maxn=1e5+5;
  8. int n,m;
  9. LL seed,vmax;
  10. LL a[maxn];
  11. struct node
  12. {
  13. int l,r;mutable LL v;
  14. node(int L,int R=-1,LL V=0):l(L),r(R),v(V){}
  15. bool operator < (const node& o) const
  16. {
  17. return l<o.l;
  18. }
  19. };
  20. set<node>s;
  21. it_ split(int pos)
  22. {
  23. it_ it=s.lower_bound(node(pos));
  24. if(it!=s.end()&& it->l==pos) return it;
  25. --it;
  26. int ll=it->l,rr=it->r;
  27. LL vv=it->v;
  28. s.erase(it);
  29. s.insert(node(ll,pos-1,vv));
  30. return s.insert(node(pos,rr,vv)).first;
  31. }
  32. void assign(int l,int r,LL val=0)
  33. {
  34. it_ itl=split(l),itr=split(r+1);
  35. s.erase(itl,itr);
  36. s.insert(node(l,r,val));
  37. }
  38. void add(int l,int r,LL val=0)
  39. {
  40. it_ itl=split(l),itr=split(r+1);
  41. for(it_ i=itl;i!=itr;++i)
  42. {
  43. i->v+=val;
  44. }
  45. }
  46. LL so(int l,int r,int k)
  47. {
  48. it_ itl=split(l),itr=split(r+1);
  49. vector<pair<LL,int>>v;
  50. v.clear();
  51. for(;itl!=itr;++itl)
  52. {
  53. v.push_back(pair<LL,int>(itl->v,itl->r-itl->l+1));
  54. }
  55. sort(v.begin(),v.end());
  56. for(vector<pair<LL,int>>::iterator it=v.begin();it!=v.end();++it)
  57. {
  58. k-=it->second;
  59. if(k<=0)return it->first;
  60. }
  61. }
  62. LL pow(LL a,LL b,LL mod)
  63. {
  64. LL ret=1;a%=mod;
  65. while(b)
  66. {
  67. if(b&1) ret=ret*a%mod;
  68. a=a*a%mod;
  69. b>>=1;
  70. }
  71. return ret%mod;
  72. }
  73. LL ok(int l,int r,LL k,LL mod)
  74. {
  75. it_ itl=split(l),itr=split(r+1);
  76. LL ans=0;
  77. for(;itl!=itr;++itl)
  78. {
  79. ans+=(LL)(itl->r-itl->l+1)*pow(itl->v,k,mod)%mod;
  80. ans%=mod;
  81. }
  82. return ans%mod;
  83. }
  84. LL rnd()
  85. {
  86. LL ret=seed;
  87. seed=(seed*7+13)%M7;
  88. return ret;
  89. }
  90. int main(int argc, char const *argv[])
  91. {
  92. ios::sync_with_stdio(0);
  93. cin>>n>>m>>seed>>vmax;
  94. for(int i=1;i<=n;++i)
  95. {
  96. a[i]=(rnd()%vmax)+1;
  97. s.insert(node(i,i,a[i]));
  98. }
  99. s.insert(node(n+1,n+1,0));
  100. for(int i=1;i<=m;++i)
  101. {
  102. int op=(rnd()%4)+1,
  103. l=(rnd()%n)+1,
  104. r=(rnd()%n)+1;LL x,y;
  105. if(l>r)
  106. swap(l,r);
  107. if(op==3)
  108. x=(rnd()%(LL)(r-l+1))+1;
  109. else
  110. x=(rnd()%vmax)+1;
  111. if(op==4)
  112. y=(rnd()%vmax)+1;
  113. if(op==1) add(l,r,x);
  114. else if(op==2) assign(l,r,x);
  115. else if(op==3) cout<<so(l,r,x)<<endl;
  116. else if(op==4) cout<<ok(l,r,x,y)<<endl;
  117. }
  118. return 0;
  119. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号