Segment tree Gugu Gu
I resolved to write the weight of a good segment tree to write it
What is the weight segment tree
Each segment tree maintenance point is the value of point, line weights and leaves point to maintain the number of times a number appeared, the parent node maintains that it represents the number of sections in the number of emerging and
Weight segment tree Basic Operation
In fact, the weight of the tree line and the basic operation is not much different tree line
Contribute
Note: Due to the number of times a leaf node represents a number appears, therefore, in the range of a few very large, we often need to put these rows of a sequence, ordered by re-assignment (because the weight value segment tree in the number itself is not important we just need to focus on the number of times it appears), which is also known as discrete
void build(int l,int r,int ro) { tr[ro].l = l,tr[ro].r = r; if(l == r)tr[ro].w = 0; else { int mid = (l + r) / 2; build(l,mid,2 * ro); build(mid + 1,r,2 * ro + 1); tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w; } }
Add to
It is to find the leaf nodes represent this number, it weights ++
void add(int x,int ro) { if(tr[ro].l == tr[ro].r && tr[ro].l == x)tr[ro].w ++; else { int mid = (tr[ro].l + tr[ro].r) / 2; if(x <= mid)add(x,2 * ro); else if(x > mid)add(x,2 * ro + 1); tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w; } }
Query Occurrences
Example: luogu p1903 reverse order
Queries and query operations segment tree of the same,
If the node represents the interval and the interval corresponding to the query and returns its weight
To query interval is within the range of the left child node to its left child node query
To query interval is within the range right child node to its right child query
Range across the range of about child node to node query, that query were to the left and right child nodes, and add and
int find(int l,int r,int ro) { if(tr[ro].l == l && tr[ro].r == r)return tr[ro].w; else { int mid = (tr[ro].l + tr[ro].r) / 2; if(r <= mid)return find(l,r,2 * ro); else if(l > mid)return find(l,r,2 * ro + 1); else return find(l,mid,2 * ro) + find(mid + 1,r,2 * ro + 1); } }
Find k-th largest number
Example: luogu p3332 [ZJOI2013] K Tarsus query (this is a relationship problem I could find in Los ri)
Finding a large number of k, it is equivalent to looking for the first kk (kk = n- k + 1) small numbers
If kk <scope left child node, looking like a child node in the left
If kk> range left child node, indicating this number in the right child node where to find the right child node, however, be noted that the value of kk to minus range left child node, to represent us in the right child tree to find the first kk - tr [zuo] .w + 1 small numbers
If it can find a leaf node, the number of leaf nodes that represent shall ask
int numk(int l,int r,int ro,int k) { if(l == r)return l; else { int mid = (l + r) / 2; if(k <= tr[2 * ro].w)return numk(l,mid,2 * ro,k); else return numk(mid + 1,r,2 * ro + 1,k - tr[ro].w); } }
40 affixed to a reverse code division
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; struct in { int w; int k; }a[500005]; struct node { int l,r,w; }tr[4000005]; void build(int l,int r,int ro) { tr[ro].l = l,tr[ro].r = r; if(l == r)tr[ro].w = 0; else { int mid = (l + r) / 2; build(l,mid,2 * ro); build(mid + 1,r,2 * ro + 1); tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w; } } int find(int l,int r,int ro) { if(tr[ro].l == l && tr[ro].r == r)return tr[ro].w; else { int mid = (tr[ro].l + tr[ro].r) / 2; if(r <= mid)return find(l,r,2 * ro); else if(l > mid)return find(l,r,2 * ro + 1); else return find(l,mid,2 * ro) + find(mid + 1,r,2 * ro + 1); } } void add(int x,int ro) { if(tr[ro].l == tr[ro].r && tr[ro].l == x)tr[ro].w ++; else { int mid = (tr[ro].l + tr[ro].r) / 2; if(x <= mid)add(x,2 * ro); else if(x > mid)add(x,2 * ro + 1); tr[ro].w = tr[2 * ro].w + tr[2 * ro + 1].w; } } bool cmp(in x,in y) { return x.w < y.w; } bool cmpp(in x,in y) { return x.k < y.k; } int main() { int n; int ans = 0; scanf("%d",&n); for(int i = 1;i <= n;i ++) { scanf("%d",&a[i].w); a[i].k = i; } sort(a + 1,a + 1 + n,cmp); for(int i = 1;i <= n;i ++) { a[i].w = i; } sort(a + 1,a + 1 + n,cmpp); build(1,n,1); for(int i = 1;i <= n;i ++) { ans += find(a[i].w,n,1); add(a[i].w,1); } printf("%d",ans); return 0; }
Welcome chiefs pointed the wrong ah