如此重口味的数据结构,网上对它的作用范围其实没有很明确的表述。
一、单点修改+区间/单点查询
不用差分,建树O(nlgn),修改O(lgn),区间查询O(lgn),单点查询O(1)
二、区间修改+RMQ查询
差分思想,建树O(nlgn),修改O(lgn),查询O(lgn)
p . s . 实际上他应该是不支持区间修改+区间和查询的,因为不用差分区间修改会很慢, 而用了差分区间和查询会很慢,还不如打普通线段树。于是我很高兴的以为学了这个就不用普通线段树了,随便挑了几题没一题可以用zkw线段树的,肥肠懵逼
到底能不能实现呢???请看到的dalao在评论里告诉我
上一道可以用zkw线段树的题:洛谷P2068 统计和 (单点修改+区间查询)
题目描述
给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=10000)个问题,求每段区间的和。时间限制1秒。
输入输出格式
输入格式:第一行1个数,表示序列的长度n
第二行1个数,表示操作的次数w
后面依次是w行,分别表示加入和询问操作
其中,加入用x表示,询问用y表示
x的格式为"x a b" 表示在序列a的位置加上b
y的格式为"y a b" 表示询问a到b区间的加和
每行一个数,分别是每次询问的结果
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100010;
int n, m, t[N], M;
void BUILD(int n)
{
for (M = 1; M < n+2; M <<= 1);
memset(t, 0, sizeof(t));
}
void UPDATE(int pos, int x)
{
pos += M;
t[pos] += x;
for (pos >>= 1; pos; pos >>= 1)
t[pos] += x;
}
int QUERY(int l, int r)
{
l += M-1;
r += M+1;
int ans = 0;
for (; l^r^1; l >>= 1, r >>= 1){
if ((~l)&1) ans += t[l^1];
if (r&1) ans += t[r^1];
}
return ans;
}
int main()
{
scanf("%d%d", &n, &m);
BUILD(n);
for (int i = 1; i <= m; i++){
char c;
int x, y;
c = getchar();
while (c != 'x' && c != 'y') c = getchar();
scanf("%d%d", &x, &y);
if (c == 'x')
UPDATE(x, y);
else if (c == 'y')
printf("%d\n", QUERY(x, y));
}
return 0;
}