一些奇怪的注意事项

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://opensource.apple.com/source/llvmgcc42/llvmgcc42-2336.9/libstdc++-v3/testsuite/ext/pb_ds/example/

https://gcc.gnu.org/onlinedocs/gcc-4.7.1/libstdc++/api/a01570.html

淘宝的pb_ds在线:

http://code.taobao.org/p/focp/src/trunk/MakeOption/MinGW/lib/gcc/mingw32/4.4.1/include/c++/ext/pb_ds/detail/thin_heap_/thin_heap_.hpp

奇怪的实验结果(失败品)

  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 }
View Code
#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;
}
View Code
#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;
}
View Code

打包好的pb_ds实例

另外,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")

 

点此下载打包好的pb_ds实例

posted @ 2018-03-17 18:39  hehe_54321  阅读(478)  评论(1编辑  收藏  举报
AmazingCounters.com