感觉这东西就是每棵线段树管的区间变了,以前学的时候线段树总是只管一个点或者管(1-i)这些点,但是这东西如果加上树状数组的思想,每棵线段树管( i-(i&-i)+1 ~ i )这些区间,那么动态修改单点就不用nlog修改只用改这个点在那log棵线段树改log*log次;查询的话变慢了点,之前的 log变成了 log * log;
精品博客 讲的真的很好 感谢大佬:
博客园 TaylorSwift13 的 树状数组套权值线段树
动态逆序对
代码
Dynamic Rankings
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <sstream>
using namespace std;
typedef long long LL;
const int N = 5e5 + 4;
int n, m;
int a[N], f[N];
int rt[N], ls[N<<6], rs[N<<6], val[N<<6], idx = 0;namespace seg
{void modify(int &u, int l, int r, int x, int f){if(!u) u = ++idx;val[u] += f;if(l==r)return ;int mid = l+r>>1;x <= mid ? modify(ls[u], l, mid, x, f) : modify(rs[u], mid+1, r, x, f);}int quary(int u, int l, int r, int L, int R){if(!u||L>r||R<l)return 0;if(L<=l&&R>=r)return val[u];int mid = l+r>>1;return quary(ls[u], l, mid, L, R) + quary(rs[u], mid+1, r, L, R);}
};namespace tree
{int quary(int u, int l, int r){int sum = 0;for(int x = u;x >= 1;x -= (x&-x))sum += seg::quary(rt[x], 0, n+1, l, r);return sum;}void modify(int u,int g, int f){for(int x = u;x <= n;x += (x&-x))seg::modify(rt[x], 0, n+1, g, f);}
};namespace tr{int tr[N]={};void modify(int u,int f){while(u<=n+1)tr[u]+=f,u+=(u&-u);}int quary(int u){int sum=0;while(u)sum+=tr[u],u-=(u&-u);return sum;}
}int main()
{scanf("%d%d",&n, &m);for(int i = 1;i <= n;i ++)scanf("%d",a + i);LL ans = 0;for(int i = 1;i <= n;i ++){ans += tree::quary(i-1, a[i]+1, n+1);tree::modify(i, a[i], 1);tr::modify(a[i], 1);f[a[i]] = i;}while(m --){int x;scanf("%d", &x); cout<<ans<<endl;ans -= tree::quary(f[x]-1, x+1, n+1);ans -= tr::quary(x-1) - tree::quary(f[x]-1, 0, x-1);tree::modify(f[x], x, -1);tr::modify(x, -1);}return 0;
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <sstream>
using namespace std;typedef long long ll;
const int N = 1e5 + 4;
int n, m;
int rt[N], ls[N<<9], rs[N<<9], val[N<<9], idx;
int x[N], cntx, y[N], cnty, a[N];int quary(int l, int r, int k)
{ if(l == r)return l;int sum = 0;for(int i = 0;i < cntx ;i ++)sum -= val[ls[x[i]]];for(int i = 0;i < cnty ;i ++)sum += val[ls[y[i]]];if(sum >= k){for(int i = 0;i < cntx ;i ++)x[i] = ls[x[i]];for(int i = 0;i < cnty ;i ++)y[i] = ls[y[i]];return quary(l, l+r>>1, k);}else {for(int i = 0;i < cntx ;i ++)x[i] = rs[x[i]];for(int i = 0;i < cnty ;i ++)y[i] = rs[y[i]];return quary((l+r>>1) + 1, r, k - sum);}
}void modify(int &u, int l, int r, int x, int f)
{if(!u)u = ++idx;val[u] += f;if(l == r)return ;int mid = l+r>>1;x <= mid ? modify(ls[u], l, mid, x, f) : modify(rs[u], mid+1, r, x, f);
}int main()
{ scanf("%d%d", &n, &m);for(int i = 1;i <= n;i ++){scanf("%d", a+i);for(int u = i;u <= n;u +=(u&-u))modify(rt[u], 0, 1e9, a[i], 1);}while(m --){char c[2];int l, r, k;scanf("%s%d%d", c, &l, &r);if(c[0]=='Q'){scanf("%d", &k);cntx = cnty = 0;for(int j = l-1;j >= 1;j -= (j&-j)) x[cntx++] = rt[j];for(int u = r;u >= 1; u -= (u&-u)) y[cnty++] = rt[u];cout<<quary(0, 1e9, k)<<endl;}else{for(int u = l;u <= n;u +=(u&-u))modify(rt[u], 0, 1e9, a[l], -1);a[l] = r;for(int u = l;u <= n;u +=(u&-u))modify(rt[u], 0, 1e9, a[l], 1);}}return 0;
}