int getsum(int x)//区间查询
{
int ans = 0;
for( ; x; x -= lowbit(x))
ans += val[x];
return ans;
}
void add(int x)//单点修改
{
for( ; x <= mx; x += lowbit(x))
val[x]++;
}
void discretize()//离散化
{
for(int i = 1; i <= n; i++)
b[i] = a[i];
sort(b + 1, b + 1 + n);
int cnt = unique(b + 1, b + 1 + n) - (b + 1);
for(int i = 1; i <= n; i++)
id[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
}
for(int i = 1; i <= n; i++)//求逆序对
{
add(id[i]);
ans += i - getsum(id[i]);
}
求逆序对的文章
树状数组总结‘’
区间修改 模板
区间修改 原理讲解
树状数组代码(good)
//设c是差分数组的前缀和
//区间修改:将l - r增加x
void add(int x, int v)
{
for( ; x <= n + 1; x += lowbit(x))
c[x] += v;
}
//给区间[l, r]加上x
void range_add(int l, int r, int x)
{
add(l,x);//将l加x
add(r+1,-x);将r + 1减x
}
//单点查询:查询x处的值
int getsum(int x)
{
int ans = 0;
for( ; x; x -= lowbit(x))
ans += c[x];
return ans;
}
//假设sum1维护d[i]的前缀和,sum2维护d[i] * i的前缀和
//在数组数组中直接修改某点的值
void add(ll p, ll x){
for(int i = p; i <= n; i += i & -i)
sum1[i] += x, sum2[i] += x * p;
}
//给区间(l, r)加上x
void range_add(ll l, ll r, ll x){
add(l, x), add(r + 1, -x);
}
//位置p的前缀和
ll ask(ll p){
ll res = 0;
for(int i = p; i; i -= i & -i)
res += (p + 1) * sum1[i] - sum2[i];
return res;
}
//区间[l, r]的和
ll range_ask(ll l, ll r){
return ask(r) - ask(l - 1);
}
LL c[mx][mx];
//单点修改,将(x, y)加上v
void add(int x, int y, int v)
{
for(int i = x; i <= n + 1; i += lowbit(i))
for(int j = y; j <= n + 1; j += lowbit(j))
c[i][j] = c[i][j] + v;
}
//区间查询: 求左上角为(1,1)右下角为(x,y) 的矩阵和
LL getsum(int x, int y)
{
LL ans = 0;
for(int i = x; i; i -= lowbit(i))
for(int j = y; j; j -= lowbit(j))
ans = ans + c[i][j];
return ans;
}
//区间查询:求(x1, y1) (x2, y2)构成的矩形的和
ans = getsum(x2, y2) - getsum(x2, y1 - 1) - getsum(x1 - 1, y2) + getsum(x1 - 1, y1 - 1)
区间修改 单点查询
//二维前缀和:
sum[i][j]=sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1]+a[i][j]
//差分数组d[i][j] 表示 a[i][j] 与 a[i−1][j]+a[i][j−1]−a[i−1][j−1] 的差。
//单点修改,将(x, y)加上v
void add(int x, int y, int v)
{
for(int i = x; i <= n + 1; i += lowbit(i))
for(int j = y; j <= n + 1; j += lowbit(j))
c[i][j] = c[i][j] + v;
}
void range_add(int xa, int ya, int xb, int yb, int z){
add(xa, ya, z);
add(xa, yb + 1, -z);
add(xb + 1, ya, -z);
add(xb + 1, yb + 1, z);
}
//区间查询: 求左上角为(1,1)右下角为(x,y) 的矩阵和
LL getsum(int x, int y)
{
LL ans = 0;
for(int i = x; i; i -= lowbit(i))
for(int j = y; j; j -= lowbit(j))
ans = ans + c[i][j];
return ans;
}
//区间修改 + 区间查询
void add(ll x, ll y, ll z){
for(int X = x; X <= n; X += X & -X)
for(int Y = y; Y <= m; Y += Y & -Y){
t1[X][Y] += z;
t2[X][Y] += z * x;
t3[X][Y] += z * y;
t4[X][Y] += z * x * y;
}
}
void range_add(ll xa, ll ya, ll xb, ll yb, ll z){ //(xa, ya) 到 (xb, yb) 的矩形
add(xa, ya, z);
add(xa, yb + 1, -z);
add(xb + 1, ya, -z);
add(xb + 1, yb + 1, z);
}
ll ask(ll x, ll y){
ll res = 0;
for(int i = x; i; i -= i & -i)
for(int j = y; j; j -= j & -j)
res += (x + 1) * (y + 1) * t1[i][j]
- (y + 1) * t2[i][j]
- (x + 1) * t3[i][j]
+ t4[i][j];
return res;
}
ll range_ask(ll xa, ll ya, ll xb, ll yb){
return ask(xb, yb) - ask(xb, ya - 1) - ask(xa - 1, yb) + ask(xa - 1, ya - 1);
}