• Codeforces 316 E3 线段树


    题目链接


    题意

    给定一个长度为(n)序列(a),需要支持如下操作

    • 单点修改

    • 对于区间([l..r]),求(sum_{i=0}^{r-l}f_i*a_{l+i}),模(10^9),其中(f)是斐波那契数列,(f_0=f_1=1)

    • 区间加

    做法

    建线段树,对于一个节点([l..r]),记

    [s_k=sum_{i=0}^{r-l}f_{i+k}*a_{l+i} ]

    存在以下性质

    [egin{align} &s_{k-2}+s_{k-1}\ =&sum_{i=0}^{r-l}(f_{i+k-2}+f_{i+k-1})*a_{l+i}\ =&sum_{i=0}^{r-l}f_{i+k}*a_{l+i}\ =&s_k end{align} ]

    只需要维护(s_0)(s_1),预处理斐波那契数列作为系数,可以(O(1))求出(s_k)

    合并两个区间的时候,需要求出第二个区间的(s_{len},s_{len+1}),其中(len)是第一个区间的长度

    区间加,可以利用$$sum_{i=0}^nf_i=f_{n+2}-1$$快速修改

    #include<cstdio>
    #include<algorithm>
    #include<ctype.h>
    #include<string.h>
    #include<math.h>
    
    using namespace std;
    #define ll long long
    
    inline char read() {
    	static const int IN_LEN = 1000000;
    	static char buf[IN_LEN], *s, *t;
    	return (s == t ? t = (s = buf) + fread(buf, 1, IN_LEN, stdin), (s == t ? -1 : *s++) : *s++);
    }
    template<class T>
    inline void read(T &x) {
    	static bool iosig;
    	static char c;
    	for (iosig = false, c = read(); !isdigit(c); c = read()) {
    		if (c == '-') iosig = true;
    		if (c == -1) return;
    	}
    	for (x = 0; isdigit(c); c = read()) x = ((x + (x << 2)) << 1) + (c ^ '0');
    	if (iosig) x = -x;
    }
    const int OUT_LEN = 10000000;
    char obuf[OUT_LEN], *ooh = obuf;
    inline void print(char c) {
    	if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), ooh = obuf;
    	*ooh++ = c;
    }
    template<class T>
    inline void print(T x) {
    	static int buf[30], cnt;
    	if (x == 0) print('0');
    	else {
    		if (x < 0) print('-'), x = -x;
    		for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
    		while (cnt) print((char)buf[cnt--]);
    	}
    }
    inline void flush() { fwrite(obuf, 1, ooh - obuf, stdout); }
    const int N = 200005, P = 1000000000;
    int n, m, f[N], a[N], lazy[N<<2];
    struct st{
    	int a, b, len;
    	inline st(){}
    	inline st(int a_, int b_, int len_){ a=a_, b=b_, len=len_;}
    	inline st operator *(const st &rhs)const{
    		return st((a+(ll)rhs.a*f[len-1]+(ll)rhs.b*f[len])%P, (b+(ll)rhs.a*f[len]+(ll)rhs.b*f[len+1])%P, len+rhs.len);
    	}
    }s[N<<2];
    void build(int l, int r, int t){
    	if(l==r) return (void)(s[t].a=s[t].b=a[l], s[t].len=1);
    	int mid=l+r>>1, k=t<<1;
    	build(l, mid, k), build(mid+1, r, k|1);
    	s[t]=s[k]*s[k|1];
    }
    inline void add(int t, int x){
    	(lazy[t]+=x)%=P;
    	s[t].a=(s[t].a+(ll)(f[s[t].len+2]-1)*x)%P;
    	s[t].b=(s[t].b+(ll)(f[s[t].len+3]-2)*x)%P;
    }
    void modify(int l, int r, int t, int x, int y){
    	if(l==r) return (void)(s[t].a=s[t].b=y);
    	int mid=l+r>>1, k=t<<1;
    	if(lazy[t]) add(k, lazy[t]), add(k|1, lazy[t]), lazy[t]=0;
    	if(x<=mid) modify(l, mid, k, x, y); else modify(mid+1, r, k|1, x, y);
    	s[t]=s[k]*s[k|1];
    }
    st query(int l, int r, int t, int L, int R){
    	if(L<=l && r<=R) return s[t];
    	int mid=l+r>>1, k=t<<1;
    	if(lazy[t]) add(k, lazy[t]), add(k|1, lazy[t]), lazy[t]=0;
    	if(R<=mid) return query(l, mid, k, L, R);
    	if(L>mid) return query(mid+1, r, k|1, L, R);
    	return query(l, mid, k, L, R)*query(mid+1, r, k|1, L, R);
    }
    void change(int l, int r, int t, int L, int R, int x){
    	if(L<=l && r<=R) return add(t, x);
    	int mid=l+r>>1, k=t<<1;
    	if(lazy[t]) add(k, lazy[t]), add(k|1, lazy[t]), lazy[t]=0;
    	if(L<=mid) change(l, mid, k, L, R, x);
    	if(R>mid) change(mid+1, r, k|1, L, R, x);
    	s[t]=s[k]*s[k|1];
    }
    int main() {
    	read(n), read(m);
    	f[1]=f[2]=1;
    	for(int i=3; i<=n+3; ++i) f[i]=(f[i-1]+f[i-2])%P;
    	for(int i=1; i<=n; ++i) read(a[i]);
    	build(1, n, 1);
    	while(m--){
    		static int opt, l, r, x;
    		read(opt), read(l), read(r);
    		if(opt==1) modify(1, n, 1, l, r);
    		else if(opt==2) print(query(1, n, 1, l, r).a), print('
    ');
    		else read(x), change(1, n, 1, l, r, x);
    	}
    	return flush(), 0;
    }
    
  • 相关阅读:
    idea实现快捷批量修改替换
    接口自动化测试:利用环境变量管理测试环境的切换
    接口自动化测试:pytest自定义fixture传参request
    接口自动化测试:python连接mysql方法封装
    接口自动化测试:yaml文件中变量替换
    接口自动化测试:测试数据生成的一个小技巧
    接口自动化测试:抓包方式理解三次握手与四次挥手
    selenium相关:selenium grid的简单用法
    APP测试学习:弱网测试
    APP测试学习:耗电量测试
  • 原文地址:https://www.cnblogs.com/CMXRYNP/p/9651026.html
Copyright © 2020-2023  润新知