前几天去海南旅行没怎么做题,倒是搞了一下多校的那个polya,现在看来如果给我多点时间我应该是能搞出来的,置换群也大概知道怎么找了,以前是没看出那个东西怎么转,现在看出来了,自然就没什么好怕的了~今天在研究Treap,觉得它的名字就是Tree和Heap派生出来的,既有树的形式,也有堆的形式,通过旋转能够平衡,下面贴下代码,代码的模板来源于某道题的标程,自己在后面加了个找第k大值的,下面是模板
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<cstdlib> using namespace std; int N=100000; const int M = 100000 << 2; int root; int size[M], number[M], args[M], key[M], indices[M][2]; int node_count; void update(int u) { size[u] = size[indices[u][0]] + size[indices[u][1]] + number[u]; } void rotate(int &u, int d) { int v = indices[u][d]; indices[u][d] = indices[v][d ^ 1]; indices[v][d ^ 1] = u; update(u); update(v); u = v; } void insert(int &u, int k) { if (u == 0) { u = ++ node_count; size[u] = number[u] = 1; key[u] = k; args[u] = rand(); indices[u][0] = indices[u][1] = 0; } else if (k == key[u]) { number[u] ++; } else { int d = k > key[u]; int &v = indices[u][d]; insert(v, k); if (args[v] < args[u]) { rotate(u, d); } } update(u); } void erase(int &u, int k) { if (u == 0) { size[u] = number[u] = indices[u][0] = indices[u][1] = 0; } else if (k == key[u]) { if (number[u] > 1) { number[u] --; } else { int d = args[indices[u][1]] < args[indices[u][0]]; rotate(u, d); erase(u, k); } } else { int d = k > key[u]; int &v = indices[u][d]; erase(v, k); if (args[v] < args[u]) { rotate(u, d); } } update(u); } bool find(int u, int k) { while (u > 0) { if (key[u] == k) { return true; } u = indices[u][k > key[u]]; } return false; } int find_greater(int u, int k) { int result = 0; while (u > 0) { if (k <= key[u]) { result += size[indices[u][1]] + number[u]; } u = indices[u][k > key[u]]; } return result; } int find_smaller(int u,int k){ int result=0; while(u>0){ if(k>=key[u]){ result+=size[indices[u][0]]+number[u]; } u=indices[u][k >= key[u]]; } return result; } int find_equal(int u,int k){ while (u > 0) { if (key[u] == k) { return number[u]; } u = indices[u][k > key[u]]; } return 0; } int find_kth(int u,int k){ if(u==0||k<=0||k>size[u]) return 0; int s1=size[indices[u][0]]; int s2=number[u]; if(s1<k&&s1+s2>=k){ return key[u]; } else if(s1+s2<k){ return find_kth(indices[u][1],k-s1-s2); } else if(s1>=k){ return find_kth(indices[u][0],k); } } #define clr(x) memset((x), 0, sizeof(x)) void init(){ clr(size);clr(number);clr(args);clr(key);clr(indices); args[0]=INT_MAX; node_count=0; root=0; } int main() { init(); int n;cin>>n; int otype,okey; while(n--) { scanf("%d%d",&otype,&okey); // 1是插入key值 2是删除key值 3是查找key值 4是询问大于等于key 5询问小于等于 6询问等于 7询问第k大的 if(otype==1){ insert(root,okey); } else if(otype==2){ erase(root,okey); } else if(otype==3){ cout<<find(root,okey)<<endl; } else if(otype==4){ cout<<find_greater(root,okey)<<endl; } else if(otype==5){ cout<<find_smaller(root,okey)<<endl; } else if(otype==6){ cout<<find_equal(root,okey)<<endl; } else if(otype==7){ cout<<find_kth(root,okey)<<endl; } } return 0; }
写了个驱动程序测试了下,感觉还行,漏洞还有待发现吧.
总结一下:
1.Treap
2.Polya定理