题目链接:点击打开链接
思路:
对于该题, 由于存在区间加一个值, 那么所有数都可能永远不会变成1, 但是数与数之间的相对值会趋近于相等。 比如1 2 3 4 5, 进行一次根号操作变成1 1 1 2 2, 而一旦如果相等, 那么他们同时加一个数也是相等的。 所以我们增加一个标记bit[rt]表示该区间内的数是否全部相等,如果相等等于什么。
细节参见代码:
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; typedef long long LL; const int maxn = 100010; LL sum[maxn<<2], add[maxn<<2]; int n, m, vv, bit[maxn<<2]; inline void PushDown(int rt,int m) { if (add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; if(bit[rt<<1]) bit[rt<<1] += add[rt]; if(bit[rt<<1|1]) bit[rt<<1|1] += add[rt]; sum[rt<<1] += add[rt] * (m - (m >> 1)); sum[rt<<1|1] += add[rt] * (m >> 1); add[rt] = 0; } } inline void PushUp(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; if(bit[rt<<1] == bit[rt<<1|1] && bit[rt<<1] && bit[rt<<1|1]) bit[rt] = bit[rt<<1]; else bit[rt] = 0; return ; } inline void build(int l, int r, int rt) { sum[rt] = 0; add[rt] = 0; bit[rt] = 0; if(l == r) { scanf("%d", &vv); sum[rt] = vv; bit[rt] = vv; return ; } int m = (l+r)>>1; build(lson); build(rson); PushUp(rt); } inline void update(int L, int R, int l, int r, int rt) { if(L<=l && r<=R && bit[rt]) { LL res = sqrt(bit[rt] + 0.5); add[rt] -= bit[rt] - res; sum[rt] = (LL)(r - l + 1) * res; bit[rt] = res; return ; } if(l == r) { sum[rt] = sqrt(sum[rt] + 0.5); return ; } int m = (l+r)>>1; PushDown(rt , r - l + 1); if(L <= m) update(L, R, lson); if(m < R) update(L, R, rson); PushUp(rt); } inline void update2(int L,int R,int c,int l,int r,int rt) { if (L <= l && r <= R) { add[rt] += c; if(bit[rt]) bit[rt] += c; sum[rt] += (LL)c * (r - l + 1); return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update2(L , R , c , lson); if (m < R) update2(L , R , c , rson); PushUp(rt); } inline LL query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return sum[rt]; } int m = (l+r)>>1; PushDown(rt , r - l + 1); LL ans = 0; if(L <= m) ans += query(L, R, lson); if(m < R) ans += query(L, R, rson); return ans; } int id[maxn], l[maxn], r[maxn], v[maxn]; int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); scanf("%d", &m); build(1, n, 1); int last = -1; for(int i = 1; i <= m; i++) { scanf("%d%d%d", &id[i], &l[i], &r[i]); if(l[i] > r[i]) swap(l[i], r[i]); if(id[i] == 1) scanf("%d", &v[i]); if(id[i] == 3) last = i; } for(int i = 1; i <= m; i++) { if(last < i) break; if(id[i] == 1) { update2(l[i], r[i], v[i], 1, n, 1); } else if(id[i] == 2) { update(l[i], r[i], 1, n, 1); } else { printf("%I64d\n", query(l[i], r[i], 1, n, 1)); } } } return 0; }
时间: 2024-10-07 09:09:04