日常训练 维护序列(包含区间除)
2017-03-29 18:45
495 查看
题意简述:修改:1 l r c:区间l∼r每个元素加上c,2 l r c:区间l∼r每个元素除以d下取整,3 l r,求l∼r的最小值,4 l r,求l∼r的区间和。序列长度n,操作数q满足n,q≤105。
除法会使区间内元素越除差别越小,当一个区间最大值和最小值因为除法而减去的数相同时可以作为一个区间减法打成tag。(具体证明不是很会)
除法会使区间内元素越除差别越小,当一个区间最大值和最小值因为除法而减去的数相同时可以作为一个区间减法打成tag。(具体证明不是很会)
#include<bits/stdc++.h> typedef long long ll; const int N = 1e5 + 50; struct rec{ int l,r,min,max,flag; long long sum; }; rec tr[N * 8]; int a ; template <typename T> void read(T &x){ x = 0;int f = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') f *= -1; c = getchar();} while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();} x *= f; } void updata(int i){ tr[i].min = std::min(tr[i * 2].min,tr[i * 2 + 1].min); tr[i].max = std::max(tr[i * 2].max,tr[i * 2 + 1].max); tr[i].sum = tr[i * 2].sum+tr[i * 2 + 1].sum; return; } void build(int i, int l, int r){ tr[i].l = l; tr[i].r = r; tr[i].flag = 0; if (l == r) {tr[i].sum = tr[i].min = tr[i].max = a[l]; return;} int mid = (l + r) >> 1; build(i * 2, l, mid); build(i * 2 + 1, mid + 1, r); updata(i); //printf("i=%d l=%d r=%d min=%d max=%d sum=%lld\n",i,l,r,tr[i].min,tr[i].max,tr[i].sum); return; } void push(int i){ if (tr[i].flag == 0) return; tr[i * 2].min += tr[i].flag; tr[i * 2 + 1].min += tr[i].flag; tr[i * 2].max += tr[i].flag; tr[i * 2 + 1].max += tr[i].flag; tr[i * 2].flag += tr[i].flag; tr[i * 2 + 1].flag += tr[i].flag; tr[i * 2].sum += (ll)tr[i].flag * (tr[i * 2].r - tr[i * 2].l + 1); tr[i * 2 + 1].sum += (ll)tr[i].flag * (tr[i * 2 + 1].r - tr[i * 2 + 1].l + 1); tr[i].flag = 0; return; } void add(int i, int l, int r, int c){ push(i); if (tr[i].l == l && tr[i].r == r){ tr[i].flag += c; tr[i].min += c; tr[i].max += c; tr[i].sum += (ll)c * (tr[i].r - tr[i].l + 1); return; } int mid = (tr[i].l + tr[i].r) >> 1; if (r <= mid) add(i * 2, l, r, c); else if (l > mid) add(i * 2 + 1, l, r, c); else{ add(i * 2, l, mid, c); add(i * 2 + 1, mid + 1, r, c); } updata(i); return; } int d(int x, int y){ int z = x / y; if (z * y > x) return z - 1; else return z; if (x < 0) return (x - y + 1) / y; else return x / y; } void div(int i, int l, int r, int c){ push(i); if (tr[i].l == l && tr[i].r == r && tr[i].min - d(tr[i].min, c) == tr[i].max - d(tr[i].max, c)){ int det = tr[i].min - d(tr[i].min, c); tr[i].min -= det; tr[i].max -= det; tr[i].flag -= det; tr[i].sum -= (ll)det * (tr[i].r - tr[i].l + 1); return; } int mid = (tr[i].l + tr[i].r) >> 1; if (r <= mid) div(i * 2, l, r, c); else if (l > mid) div(i * 2 + 1, l, r, c); else{ div(i * 2, l, mid, c); div(i * 2 + 1, mid + 1, r, c); } updata(i); return; } int query_min(int i, int l, int r){ push(i); if (tr[i].l == l && tr[i].r == r) return tr[i].min; int mid = (tr[i].l + tr[i].r) >> 1; if (r <= mid) return query_min(i * 2, l, r); if (l > mid) return query_min(i * 2 + 1, l, r); return std::min(query_min(i * 2, l, mid),query_min(i * 2 + 1, mid + 1, r)); } long long query_sum(int i, int l, int r){ push(i); if (tr[i].l == l && tr[i].r == r) return tr[i].sum; int mid = (tr[i].l + tr[i].r) >> 1; if (r <= mid) return query_sum(i * 2, l, r); if (l > mid) return query_sum(i * 2 + 1, l, r); return query_sum(i * 2, l, mid) + query_sum(i * 2 + 1, mid + 1, r); } void print_tree(){ for (int i=1; i<=9; i++) printf("i=%d l=%d r=%d min=%d max=%d flag=%d sum=%lld\n", i,tr[i].l,tr[i].r,tr[i].min,tr[i].max,tr[i].flag,tr[i].sum); printf("\n"); return; } int main(){ freopen("market.in","r",stdin); freopen("market.out","w",stdout); int n,q; read(n);read(q); for (int i=1; i<=n; i++) read(a[i]); build(1,1,n); print_tree(); int type,l,r,c; for (; q>0; q--){ read(type); if (type < 3){ read(l);read(r);read(c); l++;r++; if (type == 1) add(1,l,r,c); else div(1,l,r,c); }else{ read(l);read(r); l++;r++; if (type == 3) printf("%d\n",query_min(1,l,r)); else printf("%lld\n",query_sum(1,l,r)); } print_tree(); } return 0; }
相关文章推荐
- 【维护区间最长连续子序列 && 线段树 && 区间归并】HDU - 1540 Tunnel Warfare
- BZOJ 5039([Jsoi2014]序列维护-线段树区间加,区间乘,区间求和)
- (Relax 线段树1.1)POJ 3468 A Simple Problem with Integers(线段树子区间更新的维护:集中更新和动态统计子序列中的数据)
- bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和
- [DFS序列+线段树维护区间标记]ZOJ3686 A Simple Tree Problem
- BZOJ 1798-维护序列seq(线段树区间更新)
- HYSBZ 1798(Ahoi2009) Seq 维护序列seq(区间更新+加法乘法混合操作)
- 【BZOJ】1798: [Ahoi2009]Seq 维护序列seq 线段树多标记(区间加+区间乘)
- bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和
- 洛谷2023维护序列(线段树区间乘+区间加)
- [日常训练] 我们爱序列
- Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)
- BZOJ - 1798: [Ahoi2009]Seq 维护序列seq (线段树 区间更新)
- [BZOJ] 1798: [Ahoi2009]Seq 维护序列seq #线段树:区间加+区间乘+区间求和
- HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)
- HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)
- 序列神器伸展树 区间维护,区间提取,区间翻转的AC模板。
- MS SQL 日常维护管理
- LINQ TO SQL 之Single“序列中不包含任何元素“ 异常
- Dataguard日常维护及故障解决