一维
ll tr[maxn];
ll lowbit(ll i)
{
return i&(-i);
}
void update(ll x,ll v)
{
for(ll i=x;i<=n+5;i+=lowbit(i))
{
tr[i]=max(tr[i],v);
}
}
ll query(ll x)
{
ll maxx=0;
for(ll i=x;i>0;i-=lowbit(i))
{
maxx=max(maxx,tr[i]);
}
return maxx;
}
对A[n]分别进行如下操作m次
一维时间复杂度–O(mlogn)
二维(A[n][n])时间复杂度–O(mlognlogn)
*数组下标不能到0 *
const ll maxn = 1000 + 10;
ll c[maxn][maxn];
ll t, x, y;
ll x1, x2, y1, y2;
ll lowbit(ll i) //二进制最低位1位置
{
return i & (-i);
}
void update(ll x, ll y, ll v) //更新(二维数组)
{
for (ll i = x; i <=n; i += lowbit(i))//n为x轴或y轴大小,有时候随题意变化
{
for (ll j = y; j <=n; j += lowbit(j))
{
c[i][j] += v;
}
}
}
ll query(ll x, ll y) //查找(二维数组)
{
ll sum = 0;
for (ll i = x; i > 0; i -= lowbit(i))
{
for (ll j = y; j > 0; j -= lowbit(j)) //注意开闭区间
{
sum += c[i][j];
}
}
return sum;
}
int main()
{
update(x + 1, y + 1, 1); //若含有0,则坐标+1
printf("%lld\n", query(x2 + 1, y2 + 1) - query(x2 + 1, y1) - query(x1, y2 + 1) + query(x1, y1)); //查询给定矩形区间
}
求逆序对(离散化)
ll c[maxn];
ll n,ans,a;
struct Node
{
ll v, index;
bool operator<(Node other) const
{
if(v != other.v) return v < other.v;
else return index<other.index;//遇到存在重复元素的处理
}
} nodes[maxn];
int main()
{
// DEBUG;
while (scanf("%lld", &n)!=EOF)
{
memset(c,0,sizeof(c));
for (ll i = 1; i <= n; i++)
{
scanf("%lld", &a);
nodes[i].index = i;
nodes[i].v = a;//下标排序后的逆序数等于原序列逆序数
}
sort(nodes + 1, nodes + 1 + n);
ans = 0;
for (ll i = 1; i <= n; i++)
{
update(nodes[i].index);
ans += i - query(nodes[i].index);//求逆序对工式
}
printf("%lld\n", ans);
}
return 0;
}
离散化(求一般形式)
for (ll i = 1; i <= n; i++)
{
arr[nodes[i].index] = i;
}
update(arr[i]);
ans += query(arr[i]);
区间修改+单点查询
update(x1, y1,v); //二维
update(x2 + 1, y1,-v);
update(x1, y2 + 1,-v);
update(x2 + 1, y2 + 1,v);
update(x1, y1, z1,v); //三维
update(x2 + 1, y1, z1,-v);
update(x1, y2 + 1, z1,-v);
update(x1, y1, z2 + 1,-v);
update(x2 + 1, y2 + 1, z1,v);
update(x2 + 1, y1, z2 + 1,v);
update(x1, y2 + 1, z2 + 1,v);
update(x2 + 1, y2 + 1, z2 + 1,-v);
printf("%lld\n", query(x1, y1, z1) ); //查询方式
区间修改+区间查询(一维)
void update(ll x,ll v)
{
for (ll i = x; i <maxm; i += lowbit(i))
{
c[i]+=v;c1[i]+=v*x;
}
}
ll query(ll x)
{
ll res = 0;
for (ll i = x; i > 0; i -= lowbit(i))
{
res += c[i]*(x+1)-c1[i];
}
return res;
}
update(x,v);
update(y+1,-v);
query(r)-query(l-1);
区间修改+区间查询(二维)
void update(ll x, ll y, ll v)
{
for (ll i = x; i <= n; i += lowbit(i))
for (ll j = y; j <= m; j += lowbit(j))
{
c1[i][j] += v;
c2[i][j] += v * x;
c3[i][j] += v * y;
c4[i][j] += v * x * y;
}
}
ll query(ll x, ll y)
{
ll res = 0;
for (ll i = x; i > 0; i -= lowbit(i))
for (ll j = y; j > 0; j -= lowbit(j))
{
res+=(x + 1) * (y + 1) * c1[i][j] - (y + 1) * c2[i][j] - (x + 1) * c3[i][j] +c4[i][j];
}
return res;
}
update(x1, y1, v);
update(x2 + 1, y1, -v);
update(x1, y2 + 1, -v);
update(x2 + 1, y2 + 1, v);
query(x2 + 1, y2 + 1) - query(x2 + 1, y1) - query(x1, y2 + 1) + query(x1, y1);
树状数组求最大值
void updata(int x)
{
int lx, i;
while (x <= n)
{
h[x] = a[x];
lx = lowbit(x);
for (i=1; i<lx; i<<=1)
h[x] = max(h[x], h[x-i]);
x += lowbit(x);
}
}
int query(int x, int y)
{
int ans = 0;
while (y >= x)
{
ans = max(a[y], ans);
y --;
for (; y-lowbit(y) >= x; y -= lowbit(y))
ans = max(h[y], ans);
}
return ans;
}