UESTC 1597 An easy problem C 线段树+延迟操作+一次函数
来源:互联网 发布:ds数据精灵好用吗 编辑:程序博客网 时间:2024/05/24 04:39
An easy problem C
Time Limit: 4000/2000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)Submit Status
N个数排成一列,有三种操作。1.给一段区间内的每个数乘上一个非负整数。2.给一段区间内的每个数加上一个非负整数.3.询问一段区间的和模上P的值。
Input
第一行两个整数N(1≤N≤100000)表示数的个数,P(1≤P≤1000000000)表示模的值。接下来一行N个整数ai(0≤ai≤1000000000),接下来一行一个整数M(1≤M≤100000)表示操作数量,接下来M行每行描述一个操作。第一种操作描述:1 L R C(0≤C≤1000000000),表示把L到R这段区间每个数乘上一个C。第二种操作描述:2 L R C(0≤C≤1000000000),表示把L到R这段区间每个数加上一个C。第三种操作3 L R 表示询问L到R这段区间内的数的和模上P的值。Output
对面每个询问,输出对应的答案,每个询问占一行。Sample input and output
Sample Input Sample Output7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7
2
35
8
Source
2017 UESTC Training for Data StructuresUESTC 1597 An easy problem C
My Solution
题意:N个数排成一列,有三种操作。1.给一段区间内的每个数乘上一个非负整数。
2.给一段区间内的每个数加上一个非负整数.3.询问一段区间的和模上P的值。
线段树+延迟操作+一次函数
用2个lazy数组,分别为lazya[i], lazyb[i],
表示 lazya[i] * x + lazyb[i],
即用一个一次函数,或者说一次系数和常数项 来表示每个节点lazy数组的情况。
每次pushdown的时候,如果lazya或者lazyb有至少其中一个值需要向下传递,
则都一起操作。
先把 lazya的值传递给子节点的lazya和lazyb,然后把lazyb的值传递给子节点的lazyb。
且把lazyb传递给子节点的sum的时候,要 sum[son] = mod(sum[son] + (区间长度)*lazyb)。
然后pushup的时候维护sum%p即可。
2个注意点,一、每次+ or * 都要先取模,二、要用long long
复杂度 O(nlogn)
#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long LL;const LL MAXN = 1e5 + 8;LL sum[4*MAXN], lazya[4*MAXN], lazyb[4*MAXN];LL findans, MOD;LL sz;inline LL mod(LL x){ return x - x / MOD * MOD;}inline void init(){ memset(sum, 0, sizeof sum); memset(lazyb, 0, sizeof lazyb); for(LL i = 0; i < 4*MAXN; i++) lazya[i] = 1;}inline void pushdown(LL l, LL r, LL Ind){ LL mid = (l + r) >> 1; sum[Ind<<1] = mod(sum[Ind<<1] * lazya[Ind]); sum[Ind<<1] = mod(sum[Ind<<1] + mod((mid - l + 1)*lazyb[Ind])); sum[(Ind<<1) + 1] = mod(sum[(Ind<<1) + 1] * lazya[Ind]); sum[(Ind<<1) + 1] = mod(sum[(Ind<<1) + 1] + mod((r - (mid+1) + 1)*lazyb[Ind])); lazya[Ind<<1] = mod(lazya[Ind<<1]*lazya[Ind]); lazya[(Ind<<1) + 1] = mod(lazya[(Ind<<1) + 1]*lazya[Ind]); lazyb[Ind<<1] = mod(lazyb[Ind<<1]*lazya[Ind]); lazyb[(Ind<<1) + 1] = mod(lazyb[(Ind<<1) + 1]*lazya[Ind]); lazya[Ind] = 1; lazyb[Ind<<1] = mod(lazyb[Ind<<1] + lazyb[Ind]); lazyb[(Ind<<1) + 1] = mod(lazyb[(Ind<<1) + 1] + lazyb[Ind]); lazyb[Ind] = 0;}inline void pushup(LL Ind){ sum[Ind] = mod(sum[Ind<<1] + sum[(Ind<<1) + 1]);}inline void _Query(LL a, LL b, LL l, LL r, LL Ind){ if(a <= l && r <= b){findans = mod(findans + sum[Ind]); return; } LL mid = (l + r) >> 1; if(lazya[Ind] != 1 || lazyb[Ind] != 0) pushdown(l, r, Ind); if(a <= mid) { _Query(a, b, l, mid, Ind<<1); } if(b > mid) { _Query(a, b, mid + 1, r, (Ind<<1) + 1); } pushup(Ind);}inline void _Modify(LL a, LL b, LL l, LL r, LL Ind, LL d, bool f){ if(a <= l && r <= b){ if(f){ sum[Ind] = mod(sum[Ind] * d); lazya[Ind] = mod(lazya[Ind] * d); lazyb[Ind] = mod(lazyb[Ind] * d); } else{ sum[Ind] = mod(sum[Ind] + mod((r - l + 1)*d)); //! lazyb[Ind] = mod(lazyb[Ind] + d); } return; } LL mid = (l + r) >> 1; if(lazya[Ind] != 1 || lazyb[Ind] != 0) pushdown(l, r, Ind); if(a <= mid){ _Modify(a, b, l, mid, Ind<<1, d, f); } if(b > mid){ _Modify(a, b, mid + 1, r, (Ind<<1) + 1, d, f); } pushup(Ind);}inline void Query(LL a, LL b) {return _Query(a, b, 1, sz, 1);}inline void Modify(LL a,LL b,LL d, bool f){return _Modify(a, b, 1, sz, 1, d, f);}int main(){ #ifdef LOCAL freopen("c.txt", "r", stdin); //freopen("c.out", "w", stdout); LL T = 1; while(T--){ #endif // LOCAL //ios::sync_with_stdio(false); cin.tie(0); LL n, q, t, l, r, c, i; scanf("%lld%lld", &n, &MOD); sz = n; init(); for(i = 1; i <= n; i++){ scanf("%lld", &c); Modify(i, i, c, false); } scanf("%lld", &q); while(q--){ scanf("%lld", &t); if(t == 1){ scanf("%lld%lld%lld", &l, &r, &c); Modify(l, r, c, true); } else if(t == 2){ scanf("%lld%lld%lld", &l, &r, &c); Modify(l, r, c, false); } else{ scanf("%lld%lld", &l, &r); findans = 0; Query(l, r); printf("%lld\n", findans); } } #ifdef LOCAL cout << endl; } #endif // LOCAL return 0;}
Thank you!
------from ProLights
阅读全文
0 0
- UESTC 1597 An easy problem C 线段树+延迟操作+一次函数
- UESTC 1592 An easy problem B 线段树区间合并
- HDOJ5475 An easy problem(暴力 & 线段树)
- hdu 5475 An easy problem(线段树)
- hdu 5475 An easy problem 线段树
- hdu5475 An easy problem 线段树
- hdu 5475 An easy problem (线段树)
- hdu5475 An easy problem(线段树)
- HDU-5475-An easy problem【线段树】
- 线段树--hdu5475 An easy problem
- 线段树:CDOJ1597-An easy problem C(区间更新的线段树)
- hdu 4729 An Easy Problem for Elfness,函数式线段树
- hdu-5475-An easy problem-线段树求乘积
- HDU 5475:An easy problem 这题也能用线段树做???
- HDU5475 An easy problem 线段树单点更新
- hdu 5475 An easy problem(线段树)
- hdu 5475 An easy problem(线段树单点更新)
- HDU5475——An easy problem(线段树or暴力)
- 搭建Linux虚拟机
- CEF方面的研究(五) CEF中C++与JS交互
- 数据结构和算法的选择
- Redis3.0官方集群配置
- 我们的特斯拉战队建队啦~
- UESTC 1597 An easy problem C 线段树+延迟操作+一次函数
- 顺序容器之间的拷贝
- 使用keytool和openssl工具生成SSL双向认证密钥对和证书库
- XML解析 (python)
- ThinkPHP 3.2.3多应用开启/项目分组
- ionic3/ionic2 新建页面
- Android 平台应用使用RxAndroid
- TortoiseSVN客户端
- 自定义view(四) 方形进度条