感觉这东西就是每棵线段树管的区间变了,以前学的时候线段树总是只管一个点或者管(1-i)这些点,但是这东西如果加上树状数组的思想,每棵线段树管( i-(i&-i)+1 ~ i )这些区间,那么动态修改单点就不用nlog修改只用改这个点在那log棵线段树改log*log次;查询的话变慢了点,之前的 log变成了 log * log;
精品博客 讲的真的很好 感谢大佬:
博客园 TaylorSwift13 的 树状数组套权值线段树
动态逆序对
代码
#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;
}