Dynamic opening point
In order to reduce the spatial complexity of the weighted line segment tree, we can not directly build the structure of the whole line segment tree, but only establish a root node at the beginning. When we need to visit a sub-tree to establish, we can establish a node representing the sub-tree.
The dynamic open-point segment tree no longer uses the double numbering rule of the parent and child nodes of the complete binary tree, but uses variables to record the numbering of the left and right nodes.
The dynamic open-point segment tree with a range of 1-n is modified m times at a single point, and the node size is O(mlogn).
Example:
P1908 reverse pair
(This problem should normally be done by discretization)
code:
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> typedef long long ll; using namespace std; const int maxm=1e7+5; struct Node{ int lc,rc,sum;//lc,rc record left and right child node number }tr[maxm]; int cnt; int build(){//Returns the number of the new node cnt++; tr[cnt].lc=tr[cnt].rc=tr[cnt].sum=0; return cnt; } void init(){//Define 1 as root node cnt=1; tr[1].lc=tr[1].rc=tr[1].sum=0; } void pushup(int node){ tr[node].sum=tr[tr[node].lc].sum+tr[tr[node].rc].sum; } void update(int x,int v,int l,int r,int node){ if(l==r){ tr[node].sum+=v; return ; } int mid=(l+r)/2; if(x<=mid){ if(!tr[node].lc)tr[node].lc=build();//If the left side is empty, set it up update(x,v,l,mid,tr[node].lc); }else{ if(!tr[node].rc)tr[node].rc=build();//If the right side is empty, set it up update(x,v,mid+1,r,tr[node].rc); } pushup(node); } int ask(int st,int ed,int l,int r,int node){ if(st<=l&&ed>=r){ return tr[node].sum; } int mid=(l+r)/2; int ans=0; if(st<=mid){ if(tr[node].lc)ans+=ask(st,ed,l,mid,tr[node].lc); } if(ed>=mid){ if(tr[node].rc)ans+=ask(st,ed,mid+1,r,tr[node].rc); } return ans; } int main(){ init(); int n; scanf("%d",&n); ll ans=0; for(int i=0;i<n;i++){ int t; scanf("%d",&t); ans+=ask(t+1,1e9,1,1e9,1); update(t,1,1,1e9,1); } printf("%lld",ans); return 0; }