#include using namespace std; const int N = ( 1 << 20 ) + 1, MX = 40 * N + 5; int a[N], tree[2 * N], cntOfVertices, n; int cntOfDistinct[MX], root[2 * N], maxValueInBig[2 * N]; int leftElement[MX], rightElement[MX], toPush[MX], sz = 1; int ql, qr, qv, qlen, cl, cr; int b[N]; int getLeftSon(int v, int tl, int tr) { int tm = (tl + tr) >> 1; return ( v - (((tr - tl) << 1) + 1 ) + ((tm - tl) << 1) + 1 ); } int getRightSon(int v) { return v - 1; } void Init(int idx, int u) { cntOfDistinct[u] = 1; leftElement[u] = b[idx]; rightElement[u] = b[idx]; toPush[u] = 0; } void correct (int u, int tl, int tr) { int leftSon = getLeftSon(u, tl, tr); int rightSon = getRightSon(u); cntOfDistinct[u] = cntOfDistinct[leftSon] + cntOfDistinct[rightSon]; if (rightElement[leftSon] == leftElement[rightSon]) { --cntOfDistinct[u]; } leftElement[u] = leftElement[leftSon]; rightElement[u] = rightElement[rightSon]; } void buildSmall (int tl, int tr) { if (tl == tr) { ++cntOfVertices; Init(tl, cntOfVertices); return; } int tm = (tl + tr) >> 1; int u = cntOfVertices + ((tr - tl) << 1) + 1; toPush[u] = 0; buildSmall(tl, tm); buildSmall(tm + 1, tr); ++cntOfVertices; correct(u, tl, tr); } void buildBig (int v, int tl, int tr) { b[tl] = a[tl]; for (int i = tl + 1; i <= tr; ++i) { b[i] = max(b[i-1], a[i]); } buildSmall(tl, tr); root[v] = cntOfVertices; if (tl == tr) { maxValueInBig[v] = a[tl]; return; } int tm = (tl + tr) >> 1; buildBig((v<<1), tl, tm); buildBig((v<<1) + 1, tm + 1, tr); maxValueInBig[v] = max(maxValueInBig[(v<<1)], maxValueInBig[(v<<1)+1]); } void push(int v, int tl, int tr) { if (!toPush[v]) { return; } int leftSon = getLeftSon(v, tl, tr); int rightSon = getRightSon(v); toPush[leftSon] = toPush[v]; rightElement[leftSon] = toPush[v]; leftElement[leftSon] = toPush[v]; cntOfDistinct[leftSon] = 1; toPush[rightSon] = toPush[v]; rightElement[rightSon] = toPush[v]; leftElement[rightSon] = toPush[v]; cntOfDistinct[rightSon] = 1; toPush[v] = 0; } void updateSmall(int v, int tl, int tr, int l, int r, int value) { if (l > r){ return; } if (tl == l && tr == r) { toPush[v] = value; rightElement[v] = value; leftElement[v] = value; cntOfDistinct[v] = 1; return; } push(v, tl, tr); int tm = (tl + tr) >> 1; if ( r <= tm ) { updateSmall(getLeftSon(v, tl, tr), tl, tm, l, r, value); } else if (l >= tm + 1) { updateSmall(getRightSon(v), tm + 1, tr, l, r, value); } else { updateSmall(getLeftSon(v, tl, tr), tl, tm, l, tm, value); updateSmall(getRightSon(v), tm + 1, tr, tm + 1, r, value); } correct(v, tl, tr); } void getRange(int v, int tl, int tr, int l, int r, int value) { if (l == tl && r == tr) { if (rightElement[v] >= value) { ql = tl; qr = tr; qv = v; } else { qlen += tr - tl + 1; } return; } push(v, tl, tr); int tm = (tl + tr) >> 1; if (r <= tm) { getRange(getLeftSon(v, tl, tr), tl, tm, l, r, value); } else if (l >= tm + 1) { getRange(getRightSon(v), tm + 1, tr, l, r, value); } else { getRange(getRightSon(v), tm + 1, tr, tm + 1, r, value); getRange(getLeftSon(v, tl, tr), tl, tm, l, tm, value); } } void getRange2x(int v, int tl, int tr, int value) { if (tl == tr) { if (rightElement[v] < value){ ++qlen; } return; } push(v, tl, tr); int tm = (tl + tr) >> 1; int leftSon = getLeftSon(v, tl, tr); int rightSon = getRightSon(v); int leftMax = rightElement[leftSon]; if (value > leftMax) { qlen += tm - tl + 1; getRange2x(rightSon, tm + 1, tr, value); } else { getRange2x(leftSon, tl, tm, value); } } void updateBig(int v, int tl, int tr, int idx, int value) { ql = 0; qr = 0; qlen = 0; getRange(root[v], tl, tr, idx, tr, value); int rIdx; if (!ql){ rIdx = tr; } else { getRange2x(qv, ql, qr, value); rIdx = idx + qlen - 1; } updateSmall(root[v], tl, tr, idx, rIdx, value); if (tl == tr) { maxValueInBig[v] = value; return; } int tm = (tl + tr) >> 1; if (idx <= tm) { updateBig((v<<1), tl, tm, idx, value); } else { updateBig((v<<1) + 1, tm + 1, tr, idx, value); } maxValueInBig[v] = max(maxValueInBig[(v << 1)], maxValueInBig[(v << 1) + 1]); } int getSmall(int v, int tl, int tr, int l, int r) { if (l == -1 || r == -1 || l > r) { return 0; } if (tl == l && tr == r) { return cntOfDistinct[v]; } push(v, tl, tr); int tm = (tl + tr) >> 1; if (r <= tm) { return getSmall(getLeftSon(v, tl, tr), tl, tm, l, r); } if (l >= tm + 1) { return getSmall(getRightSon(v), tm + 1, tr, l, r); } int leftSon = getLeftSon(v, tl, tr); int rightSon = getRightSon(v); int res = getSmall(leftSon, tl, tm, l, tm) + getSmall(rightSon, tm + 1, tr, tm + 1, r); if (rightElement[leftSon] == leftElement[rightSon]) { res--; } return res; } int getIdxInSmall(int v, int tl, int tr, int x) { if (tl == tr) { if (rightElement[v] >= x) { return tl; } return -1; } push(v, tl, tr); int tm = (tl + tr) >> 1; int leftSon = getLeftSon(v, tl, tr); int leftMax = rightElement[leftSon]; int rightSon = getRightSon(v); if (leftMax >= x) { return getIdxInSmall(leftSon, tl, tm, x); } return getIdxInSmall(rightSon, tm + 1, tr, x); } int getMaxInBig(int l, int r) { l += sz - 1; r += sz - 1; int res = 0; while (l <= r) { if (l % 2 == 1) { res = max(maxValueInBig[l], res); ++l; } if (r % 2 == 0) { res = max(maxValueInBig[r], res); --r; } l >>= 1; r >>= 1; } return res; } int getBig(int v, int tl, int tr, int l, int r, int yl, int yr) { if (yl > yr){ return 0; } if (l == tl && r == tr) { int idxL = getIdxInSmall(root[v], tl, tr, yl); int idxR = getIdxInSmall(root[v], tl, tr, yr); return getSmall(root[v], tl, tr, idxL, idxR); } int tm = (tl + tr) >> 1; if (r <= tm) { return getBig((v<<1), tl, tm, l, r, yl, yr); } if (l >= tm + 1) { return getBig((v<<1) + 1, tm + 1, tr, l, r, yl, yr); } int leftMax = getMaxInBig(cl, tm); if (leftMax < yl) { return getBig((v<<1) + 1, tm + 1, tr, tm + 1, r, yl, yr); } if (leftMax >= yl && leftMax < yr) { return getBig((v<<1), tl, tm, l, tm, yl, leftMax) + getBig((v<<1) + 1, tm + 1, tr, tm + 1, r, leftMax + 1, yr); } return getBig((v<<1), tl, tm, l, tm, yl, yr); } int main() { //freopen("input.txt", "r", stdin); //freopen("outputSol.txt", "w", stdout); int q, cases; scanf("%d", &cases); for (int pCases = 1; pCases <= cases; ++pCases) { scanf("%d %d", &n, &q); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } scanf("\n"); sz = 1; while (sz < n) { sz *= 2; } cntOfVertices = 0; buildBig(1, 1, sz); for (int i = 1; i <= q; ++i){ char type; scanf("%c",&type); if (type == '+') { int idx, value; scanf("%d %d", &idx, &value); cl = idx; a[idx] += value; updateBig(1, 1, sz, idx, a[idx]); } else { int idx, yl, yr; scanf("%d %d %d",&idx,&yl,&yr); cl = idx; int low = idx - 1, high = n + 1, mid; while (high - low > 1) { mid = (low + high) >> 1; if (getMaxInBig(idx, mid) >= yr) { high = mid; } else { low = mid; } } high = min(n, high); int ans = getBig(1, 1, sz, idx, n, yl, getMaxInBig(idx, high)); printf("%d\n",ans); } scanf("\n"); } for (int i = 1; i <= sz; ++i) { a[i] = 0; } } }