ABBYY Cup 3.0 E3
来源:互联网 发布:数据库设计实例 教材 编辑:程序博客网 时间:2024/04/18 08:27
E3. Summer Homework(线段树+矩阵)
题目链接
题意是给一个序列,支持三种操作
1、把第x个数改为v
2、求l到r之间的和
3、给l到r之间加上一个数字
和函数定义是Sum(l,r) = a[l]*f[0] + a[l+1]*f[1] + a[l+2]*f[2] + ……+a[r]*f[r-l]
f[]为斐波那契数列
这个题其实即使没有第一种第三种操作,也是很难做的 ,我们考虑用一个 线段树来维护,
比如[1,8]这个区间,线段树中[1,4]这个节点我们存一个(a1*f0+……+a4*f3),[5,8]这个节点我们可以存(a5*f0+……+a8*f3),但是怎么把这两段合并到[1,8]这个节点上去呢
1*a5 + 1*a6 + 2*a7 + 3*a8=>1*a5 + 2 * a6 + 3 * a7 + 5 *a8
右边减去左边得到 0*a5 + 1 * a6 + 1 * a7 + 2 *a8
以此类推,可以得到合并后的结果
于是我们线段树节点中存两个东西[A,B],利用斐波那契的矩阵,右子树乘上x次之后(x为左子树区间的长度),合并可得到当前节点的值
在查询的时候也同理进行合并,然后第一种和第三种操作,我们可以很容易算出其每次加的数字对整段的贡献,直接加上去就行
#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<list>#include<stack>#include<queue>#include<iostream>#include<stdlib.h>using namespace std;#define LONG long longconst LONG INF=0x3f3f3f3f;const LONG MOD=1e9 ;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10#define lson l , mid , rt<< 1#define rson mid + 1 ,r , (rt<<1)|1//#define root 1, n , 1struct Matr{ LONG matr[2][2] ; void Init() { clr0(matr) ; }} F[210000] ;Matr Multi(Matr a , Matr b){ Matr res ; res.Init() ; for(int i = 0 ; i < 2 ; ++ i) for(int j = 0 ; j < 2 ; ++ j) for(int k = 0 ; k < 2 ; ++ k) res.matr[i][j] = (res.matr[i][j] + a.matr[i][k] * b.matr[k][j]) % MOD ; return res ;}Matr X;LONG Fib[201000] ;LONG a[200100] ;struct Tree{ LONG A , B ;}tree[200010*4] ;LONG lazy[200010 * 4] ;void Push_up(int l,int r ,int rt ){ int mid = (l+r) / 2; Matr tmp = F[mid-l +1]; tree[rt].A = tree[rt<<1].A + (tree[rt<<1|1].A *tmp.matr[0][0] % MOD ) + (tree[rt<<1|1].B * tmp.matr[1][0] % MOD ) ;tree[rt].A %= MOD ; tree[rt].B = tree[rt<<1].B + ( tree[rt<<1|1].A*tmp.matr[0][1] % MOD) + ( tree[rt<<1|1].B*tmp.matr[1][1]%MOD ) ;tree[rt].B %= MOD ;}void Build(int l ,int r ,int rt ){ lazy [rt] = 0 ; if(l == r) { tree[rt].A = a[l] ; tree[rt].B = 0 ; return ; } int mid = (l+r)/2 ; Build(lson ) ; Build( rson ) ; Push_up( l , r , rt ) ;}void Push_down(int l, int r ,int rt ){ int mid = (l +r) /2 ; if(lazy[rt]) { LONG ret1 = (F[mid - l +1 +2-1].matr[0][0] - 1) * lazy[rt] % MOD ; LONG ret2 = (F[mid-l + 2-1].matr[0][0] - 1) * lazy[rt] % MOD ; tree[rt<<1].A = (tree[rt<<1].A + ret1) % MOD ; tree[rt<<1].B = (tree[rt<<1].B + ret2) % MOD ; ret1 = (F[r-mid + 2-1].matr[0][0] - 1) * lazy[rt]% MOD ; ret2 = (F[r - mid - 1 + 2 -1].matr[0][0] - 1) * lazy[rt] % MOD ; tree[rt<<1|1].A = (tree[rt<<1|1].A + ret1 ) % MOD ; tree[rt<<1|1].B = (tree[rt<<1|1].B + ret2) % MOD ; lazy[rt<<1] += lazy[rt] ;lazy[rt<<1] %= MOD ; lazy[rt<<1|1] += lazy[rt] ; lazy[rt<<1|1] %= MOD ; lazy[rt] = 0 ; }}void Update1(int L ,int R , int l , int r ,int rt , LONG val){ if(L <= l && r <= R ) { LONG ret1 = (F[r-l+1 + 2-1].matr[0][0] - 1)*val % MOD ; LONG ret2 = (F[r-l + 2-1].matr[0][0] - 1) * val % MOD ; tree[rt].A = (tree[rt].A +ret1 )%MOD ; tree[rt].B =(tree[rt].B + ret2 ) % MOD ; lazy[rt] += val ; return ; } Push_down(l , r , rt ) ; int mid = (l + r ) / 2; if(L <= mid) Update1(L , R , lson , val ) ; if(R > mid ) Update1(L ,R , rson , val) ; Push_up(l , r, rt) ;}Tree Que(int L ,int R ,int l ,int r , int rt ){ if(L <= l && r <=R) return tree[rt] ; int mid = (l + r) / 2; Push_down(l , r , rt ) ; Tree res1 , res2,ans ; if(L <= mid && R <= mid ) return Que(L , R , lson ) ; else if(L > mid && R > mid ) return Que(L ,R ,rson ) ; else { Matr tmp = F[mid-max(L,l)+1] ; res1 = Que(L,R,lson ) ; res2 = Que(L ,R ,rson ) ; ans.A = ( res1.A + (res2.A *tmp.matr[0][0] % MOD ) + (res2.B * tmp.matr[1][0] % MOD ) )%MOD ; ans.B = ( res1.B + (res2.A*tmp.matr[0][1] % MOD) + ( res2.B*tmp.matr[1][1]%MOD ) ) % MOD ; return ans ; }}int main(){ int n , m ; X.matr[0][0] = 1 ; X.matr[1][0] = 1 ;X.matr[0][1] = 1 ;X.matr[1][1] = 0 ; F[1] = X ; for(int i = 2 ; i <= 200000 ; ++i) F[i] = Multi(F[i-1] , X) ; while(cin >> n >> m) { for(int i = 1 ;i <= n ; ++ i) scanf( "%lld",&a[i] ) ; Build(1,n,1) ; int t ; int l , r ; LONG val ; LONG temp ; Tree RES ; while(m -- ) { scanf("%d",&t) ; if(t == 1) { scanf("%d%lld",&l,&val) ; RES = Que(l,l,1,n,1) ; temp = val - RES.A ; Update1(l , l ,1,n,1,temp ) ; } else if(t ==2 ) { scanf("%d%d",&l,&r) ; RES = Que(l ,r , 1,n,1) ; printf("%lld\n",RES.A) ; } else { scanf("%d%d%lld",&l,&r,&val) ; Update1(l ,r ,1,n,1,val) ; } } }}
阅读全文
1 0
- ABBYY Cup 3.0 E3
- ABBYY Cup 3.0 - Finals(总结)
- codeforces ABBYY Cup 2.0
- Abbyy Cup 2.0
- codeforces ABBYY Cup 3.0 - Finals (online version) B2. Shave Beaver!
- Codeforces ABBYY Cup 3.0 / 316A1 316A2 Special Task(模拟&贪心&组合数学)
- [ST表] Codeforces Abbyy Cup 2.0-Final B Sequence
- ABBYY
- ABBYY Cup 2.0 - Easy, problem: (C1) Party 并查集水题
- Cup
- Cup
- Cup
- cup
- study E3
- 2010 E3
- 生素E3
- E3 V2配置实物
- 7E3 Banding
- 请检查如下代码,如有问题,请正确指出!(java、多线程)
- Centos7 安装tomcat 开机启动
- scrapy安装出错总结
- oracle时间分钟格式注意事项
- 食物链
- ABBYY Cup 3.0 E3
- JavaBean的设计原则
- BZOJ3881: [Coci2015]Divljak
- 易宝支付基于Kubernetes的私有容器云从0到1的建设之路
- 判断是否离开当前页面
- epoll边缘触发(epoll et) 源代码例子
- JavaScript Math
- QT设置界面大小
- 无限轮播