一些奇怪的注意事项
1.unique函数
听说并没有把重复的元素放到原数组的最后,网上的某些说法可能是错的
upd:http://zh.cppreference.com/w/cpp/algorithm/unique:
指向范围的新逻辑结尾和物理结尾之间元素的迭代器仍然可解引用,但元素自身拥有未指定值
2.multiset
multiset/unordered_multiset的count函数的复杂度与直觉上认为的不太一样
见
http://www.cplusplus.com/reference/set/multiset/count/#complexity
http://zh.cppreference.com/w/cpp/container/unordered_multiset/count
与找到的元素个数成线性,而不是直觉上认为的O(log n)以及平均O(1)
如果有此需求可以换成map/unordered_map
3.ext/pb_ds/tree_policy.hpp
不要再想着用这个维护奇奇怪怪的标记了.....
研究了5个小时啥有实际意义的也没研究出来....就连个支持find_by_order的multiset(支持重复元素)都没做出来
不过倒是有了一点想法:如果真的要入手,可以从stl源码里面把tree_order_statistics_node_update.hpp拖出来,在此基础上改
另外,如果要pb_ds里的树支持重复元素,可以考虑用另一个map来辅助,然后树里面不直接存数据,存pair<数据,一个序号>。具体不细讲了。不过这种情况下要支持split和join就很麻烦了23333
有两个文档和实例的链接:
https://gcc.gnu.org/onlinedocs/gcc-4.7.1/libstdc++/api/a01570.html
淘宝的pb_ds在线:
奇怪的实验结果(失败品)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #include<ext/pb_ds/tree_policy.hpp> 3 #include<ext/pb_ds/assoc_container.hpp> 4 using namespace std; 5 using namespace __gnu_pbds; 6 7 namespace myspace 8 { 9 template<typename key_type,typename size_type> 10 struct myData//记住一定要放在外面 11 { 12 myData():num(0),size(0){} 13 size_type num; 14 //key_type sum; 15 size_type size; 16 }; 17 template<typename Node_CItr, typename Node_Itr, 18 typename Cmp_Fn, typename _Alloc> 19 class tree_order_statistics_node_update : private detail::branch_policy<Node_CItr, Node_Itr, _Alloc> 20 { 21 public: 22 typedef detail::branch_policy<Node_CItr, Node_Itr, _Alloc> base_type; 23 24 typedef Cmp_Fn cmp_fn; 25 typedef _Alloc allocator_type; 26 typedef typename allocator_type::size_type size_type; 27 typedef typename base_type::key_type key_type; 28 typedef typename base_type::key_const_reference key_const_reference; 29 30 typedef tree_order_statistics_node_update<Node_CItr, Node_Itr, Cmp_Fn, _Alloc> this_type; 31 32 typedef myData<key_type,size_type> metadata_type; 33 typedef Node_CItr node_const_iterator; 34 typedef Node_Itr node_iterator; 35 typedef typename node_const_iterator::value_type const_iterator; 36 typedef typename node_iterator::value_type iterator; 37 38 typedef typename base_type::const_reference const_reference; 39 typedef typename base_type::const_pointer const_pointer; 40 typedef typename _Alloc::template rebind<metadata_type>::other __rebind_m; 41 typedef typename __rebind_m::const_reference metadata_const_reference; 42 typedef typename __rebind_m::reference metadata_reference; 43 44 inline const_iterator find_by_order(size_type order) const 45 { 46 return const_cast<this_type*>(this)->find_by_order(order); 47 } 48 inline node_iterator findx(const key_type& x) 49 { 50 node_iterator it = node_begin(); 51 node_iterator end_it = node_end(); 52 53 const cmp_fn& r_cmp_fn = const_cast<this_type*>(this)->get_cmp_fn(); 54 while (it != end_it) 55 { 56 if (r_cmp_fn(x, this->extract_key(**it))) 57 it = it.get_l_child(); 58 else if (r_cmp_fn(this->extract_key(**it), x)) 59 it = it.get_r_child(); 60 else 61 it = end_it; 62 } 63 return it; 64 } 65 inline iterator find_by_order(size_type order) 66 //定义:将集合中元素从小到大(less<>)从0开始编号,找到第order大的元素 67 { 68 node_iterator it = node_begin(); 69 node_iterator end_it = node_end(); 70 71 while (it != end_it) 72 { 73 node_iterator l_it = it.get_l_child(); 74 const size_type o = (l_it == end_it)? 0 : l_it.get_metadata().size; 75 const size_type t = (it == end_it)? 0 : it.get_metadata().num; 76 if (order >= o && order < o + t) 77 return *it; 78 else if (order < o) 79 it = l_it; 80 else 81 { 82 order -= o + t; 83 it = it.get_r_child(); 84 } 85 } 86 return base_type::end_iterator(); 87 } 88 inline void addnum(const key_type& x) 89 { 90 node_iterator it=findx(x); 91 node_iterator end_it = node_end(); 92 if(it!=end_it) 93 { 94 const_cast<size_type&>(it.get_metadata().num)++; 95 } 96 } 97 inline void delnum(const key_type& x) 98 { 99 node_iterator it=findx(x); 100 node_iterator end_it = node_end(); 101 if(it!=end_it) 102 { 103 const_cast<size_type&>(it.get_metadata().num)--; 104 } 105 } 106 inline size_type getsize() 107 { 108 node_iterator it = node_begin(); 109 node_iterator end_it = node_end(); 110 if(it!=end_it) return it.get_metadata().size; 111 else return 0; 112 } 113 inline size_type getnum(const key_type& x) 114 { 115 node_iterator it=findx(x); 116 node_iterator end_it = node_end(); 117 if(it!=end_it) 118 { 119 return it.get_metadata().num; 120 } 121 return 0; 122 } 123 // inline size_type order_of_key(key_const_reference r_key) const 124 // { 125 // node_const_iterator it = node_begin(); 126 // node_const_iterator end_it = node_end(); 127 // 128 // const cmp_fn& r_cmp_fn = const_cast<this_type*>(this)->get_cmp_fn(); 129 // size_type ord = 0; 130 // while (it != end_it) 131 // { 132 // node_const_iterator l_it = it.get_l_child(); 133 // 134 // if (r_cmp_fn(r_key, this->extract_key(*(*it)))) 135 // it = l_it; 136 // else if (r_cmp_fn(this->extract_key(*(*it)), r_key)) 137 // { 138 // ord += (l_it == end_it)? 1 : 1 + l_it.get_metadata().size; 139 // it = it.get_r_child(); 140 // } 141 // else 142 // { 143 // ord += (l_it == end_it)? 0 : l_it.get_metadata().size; 144 // it = end_it; 145 // } 146 // } 147 // return ord; 148 // } 149 150 inline void operator()(node_iterator node_it, node_const_iterator end_nd_it) const 151 { 152 node_iterator l_it = node_it.get_l_child(); 153 const size_type l_rank = (l_it == end_nd_it) ? 0 : l_it.get_metadata().size; 154 //const key_type l_sum = (l_it == end_nd_it) ? 0 : l_it.get_metadata().sum; 155 156 node_iterator r_it = node_it.get_r_child(); 157 const size_type r_rank = (r_it == end_nd_it) ? 0 : r_it.get_metadata().size; 158 //const key_type r_sum = (r_it == end_nd_it) ? 0 : r_it.get_metadata().sum; 159 160 const size_type this_size = (node_it == end_nd_it) ? 0 : node_it.get_metadata().num; 161 //const key_type this_sum = (node_it == end_nd_it) ? 0 : **node_it; 162 const_cast<size_type&>(node_it.get_metadata().size)= this_size + l_rank + r_rank; 163 //const_cast<key_type&>(node_it.get_metadata().sum)= l_sum + r_sum + this_sum; 164 } 165 166 ~tree_order_statistics_node_update() 167 { } 168 169 virtual node_const_iterator 170 node_begin() const = 0; 171 172 virtual node_iterator 173 node_begin() = 0; 174 175 virtual node_const_iterator 176 node_end() const = 0; 177 178 virtual node_iterator 179 node_end() = 0; 180 181 virtual cmp_fn& 182 get_cmp_fn() = 0; 183 184 }; 185 } 186 int n,k,x,addx,anss; 187 char tmp[20]; 188 tree<int,null_type,less<int>,rb_tree_tag,myspace::tree_order_statistics_node_update> s,s2; 189 int main() 190 { 191 int i; 192 scanf("%d%d",&n,&k); 193 for(i=1;i<=n;i++) 194 { 195 scanf("%s%d",tmp,&x); 196 //printf("a%d\n",x); 197 if(tmp[0]=='I') 198 { 199 if(x<k) continue; 200 if(s.getnum(x-addx)==0) puts("a"),s.insert(x-addx); 201 s.addnum(x-addx); 202 printf("%d\n",s.getsize()); 203 } 204 else if(tmp[0]=='A') 205 { 206 addx+=x; 207 //printf("%d\n",addx); 208 } 209 else if(tmp[0]=='S') 210 { 211 addx-=x; 212 s.split(k-addx-1,s2);anss+=s.getsize();s.swap(s2); 213 //printf("%d\n",k-addx-1); 214 } 215 else if(tmp[0]=='F') 216 { 217 if((unsigned)x>s.getsize()) printf("-1\n"); 218 else printf("%d\n",*s.find_by_order(s.getsize()-x)+addx); 219 } 220 } 221 printf("%d\n",anss); 222 return 0; 223 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/assoc_container.hpp> using namespace std; using namespace __gnu_pbds; namespace myspace { template<typename key_type,typename size_type> struct myData//记住一定要放在外面 { myData():num(0),size(0){} size_type num; //key_type sum; size_type size; }; template<typename Node_CItr, typename Node_Itr, typename Cmp_Fn, typename _Alloc> class tree_order_statistics_node_update : private detail::branch_policy<Node_CItr, Node_Itr, _Alloc> { public: typedef detail::branch_policy<Node_CItr, Node_Itr, _Alloc> base_type; typedef Cmp_Fn cmp_fn; typedef _Alloc allocator_type; typedef typename allocator_type::size_type size_type; typedef typename base_type::key_type key_type; typedef typename base_type::key_const_reference key_const_reference; typedef tree_order_statistics_node_update<Node_CItr, Node_Itr, Cmp_Fn, _Alloc> this_type; typedef myData<key_type,size_type> metadata_type; typedef Node_CItr node_const_iterator; typedef Node_Itr node_iterator; typedef typename node_const_iterator::value_type const_iterator; typedef typename node_iterator::value_type iterator; typedef typename base_type::const_reference const_reference; typedef typename base_type::const_pointer const_pointer; typedef typename _Alloc::template rebind<metadata_type>::other __rebind_m; typedef typename __rebind_m::const_reference metadata_const_reference; typedef typename __rebind_m::reference metadata_reference; inline const_iterator find_by_order(size_type order) const { return const_cast<this_type*>(this)->find_by_order(order); } inline node_iterator findx(const key_type& x) { node_iterator it = node_begin(); node_iterator end_it = node_end(); const cmp_fn& r_cmp_fn = const_cast<this_type*>(this)->get_cmp_fn(); while (it != end_it) { if (r_cmp_fn(x, this->extract_key(**it))) it = it.get_l_child(); else if (r_cmp_fn(this->extract_key(**it), x)) it = it.get_r_child(); else it = end_it; } return it; } inline iterator find_by_order(size_type order) //定义:将集合中元素从小到大(less<>)从0开始编号,找到第order大的元素 { node_iterator it = node_begin(); node_iterator end_it = node_end(); while (it != end_it) { node_iterator l_it = it.get_l_child(); const size_type o = (l_it == end_it)? 0 : l_it.get_metadata().size; const size_type t = (it == end_it)? 0 : it.get_metadata().num; if (order >= o && order < o + t) return *it; else if (order < o) it = l_it; else { order -= o + t; it = it.get_r_child(); } } return base_type::end_iterator(); } inline void addnum(const key_type& x) { node_iterator it=findx(x); node_iterator end_it = node_end(); if(it!=end_it) { const_cast<size_type&>(it.get_metadata().num)++; } } inline void delnum(const key_type& x) { node_iterator it=findx(x); node_iterator end_it = node_end(); if(it!=end_it) { const_cast<size_type&>(it.get_metadata().num)--; } } inline size_type getsize() { node_iterator it = node_begin(); node_iterator end_it = node_end(); if(it!=end_it) return it.get_metadata().size; else return 0; } inline size_type getnum(const key_type& x) { node_iterator it=findx(x); node_iterator end_it = node_end(); if(it!=end_it) { return it.get_metadata().num; } return 0; } // inline size_type order_of_key(key_const_reference r_key) const // { // node_const_iterator it = node_begin(); // node_const_iterator end_it = node_end(); // // const cmp_fn& r_cmp_fn = const_cast<this_type*>(this)->get_cmp_fn(); // size_type ord = 0; // while (it != end_it) // { // node_const_iterator l_it = it.get_l_child(); // // if (r_cmp_fn(r_key, this->extract_key(*(*it)))) // it = l_it; // else if (r_cmp_fn(this->extract_key(*(*it)), r_key)) // { // ord += (l_it == end_it)? 1 : 1 + l_it.get_metadata().size; // it = it.get_r_child(); // } // else // { // ord += (l_it == end_it)? 0 : l_it.get_metadata().size; // it = end_it; // } // } // return ord; // } inline void operator()(node_iterator node_it, node_const_iterator end_nd_it) const { node_iterator l_it = node_it.get_l_child(); const size_type l_rank = (l_it == end_nd_it) ? 0 : l_it.get_metadata().size; //const key_type l_sum = (l_it == end_nd_it) ? 0 : l_it.get_metadata().sum; node_iterator r_it = node_it.get_r_child(); const size_type r_rank = (r_it == end_nd_it) ? 0 : r_it.get_metadata().size; //const key_type r_sum = (r_it == end_nd_it) ? 0 : r_it.get_metadata().sum; const size_type this_size = (node_it == end_nd_it) ? 0 : node_it.get_metadata().num; //const key_type this_sum = (node_it == end_nd_it) ? 0 : **node_it; const_cast<size_type&>(node_it.get_metadata().size)= this_size + l_rank + r_rank; //const_cast<key_type&>(node_it.get_metadata().sum)= l_sum + r_sum + this_sum; } ~tree_order_statistics_node_update() { } virtual node_const_iterator node_begin() const = 0; virtual node_iterator node_begin() = 0; virtual node_const_iterator node_end() const = 0; virtual node_iterator node_end() = 0; virtual cmp_fn& get_cmp_fn() = 0; }; } int n,k,x,addx,anss; char tmp[20]; tree<int,null_type,less<int>,rb_tree_tag,myspace::tree_order_statistics_node_update> s,s2; int main() { int i; scanf("%d%d",&n,&k); for(i=1;i<=n;i++) { scanf("%s%d",tmp,&x); //printf("a%d\n",x); if(tmp[0]=='I') { if(x<k) continue; if(s.getnum(x-addx)==0) puts("a"),s.insert(x-addx); s.addnum(x-addx); printf("%d\n",s.getsize()); } else if(tmp[0]=='A') { addx+=x; //printf("%d\n",addx); } else if(tmp[0]=='S') { addx-=x; s.split(k-addx-1,s2);anss+=s.getsize();s.swap(s2); //printf("%d\n",k-addx-1); } else if(tmp[0]=='F') { if((unsigned)x>s.getsize()) printf("-1\n"); else printf("%d\n",*s.find_by_order(s.getsize()-x)+addx); } } printf("%d\n",anss); return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/assoc_container.hpp> using namespace std; using namespace __gnu_pbds; typedef pair< unsigned int, unsigned int> interval; template<class Const_Node_Iterator, class Node_Iterator, class Cmp_Fn, class Allocator> struct intervals_node_update { public: typedef unsigned int metadata_type; bool overlaps(const interval& r_interval) { Const_Node_Iterator nd_it = node_begin(); Const_Node_Iterator end_it = node_end(); while (nd_it != end_it) { if (r_interval.second >= (*nd_it)->first&& r_interval.first <= (*nd_it)->second) return true; Const_Node_Iterator l_nd_it = nd_it.get_l_child(); const unsigned int l_max_endpoint =(l_nd_it == end_it)? 0 : l_nd_it.get_metadata(); if (l_max_endpoint >= r_interval.first) nd_it = l_nd_it; else nd_it = nd_it.get_r_child(); } return false; } protected: inline void operator()(Node_Iterator nd_it, Const_Node_Iterator end_nd_it) { const unsigned int l_max_endpoint =(nd_it.get_l_child() == end_nd_it)? 0 : nd_it.get_l_child().get_metadata(); const unsigned int r_max_endpoint =(nd_it.get_r_child() == end_nd_it)? 0 : nd_it.get_r_child().get_metadata(); const_cast<unsigned int&>(nd_it.get_metadata()) = max((*nd_it)->second, max<unsigned int>(l_max_endpoint, r_max_endpoint)); } virtual Const_Node_Iterator node_begin() const = 0; virtual Const_Node_Iterator node_end() const = 0; virtual ~intervals_node_update() { } }; typedef interval P; tree<P,null_type,less<P>,rb_tree_tag,intervals_node_update> s; int main() { s.insert(P(1,4)); s.insert(P(6,8)); s.insert(P(11,16)); cout<<s.overlaps({12,18}); return 0; }
另外,stl的rope的迭代器不支持用来动态维护元素排名,因为改变一个元素之后所有之前取出来的迭代器都会失效,这个跟实现有关系
4.vector
reserve(cnt)预分配空间使空间量达到cnt,但不实际改变size
resize(cnt,x=0)实际地改变size到cnt,如果当前size小于cnt则末尾补x
如果vec初始size小于cnt,那么vec.reserve(cnt);vec.resize(cnt);可以使得新size为cnt,且分配的空间恰为cnt所需空间
5.tr2/dynamic_bitset
已经确认是不能用的,有非常大的问题,根本就不完整
线段树
空间$2^{ceil(log2(n))+1}$
gcc/g++特性:
1.
-ftrapv检测(简单的)有符号数溢出(还是挺有用的,提醒爆int/longlong)
-fsanitize=address检测非法内存访问(很可能不能用)(要保证在加上这一行编译参数之前加上-lasan)
-std=标准名字(比如-std=gnu++17)
静态链接器:-static -static-libstdc++ -static-libgcc
2.扩栈
(也许可用?)-Wl,--stack=栈大小
3.程序里加gcc/g++参数
#pragma GCC diagnostic error "参数"
(例如:#pragma GCC diagnostic error "-fwhole-program")
还有一些,如
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")