题意:执行相应的4种操作。
思路:单点更新时求最近fib,维护fib的和及元素的和。注意初始化的时候要对每个0求fib。
#include<iostream> #include<vector> #include<map> #include<algorithm> #include<cstring> #include<cstdio> #include<cstdlib> #include<string> #define LL long long #define MAXN 100001<<2 using namespace std; vector<LL> fib; void init() { fib.push_back(1); fib.push_back(1); int i=0; while(i<90) { fib.push_back(fib[fib.size()-2]+fib[fib.size()-1]); i++; } } LL myabs(LL a) { return a>0?a:-a; } int getPosofFib(LL val) { if(val<=0) return 0; int p=lower_bound(fib.begin(),fib.end(),val)-fib.begin(); if(p==0) return 0; LL a=myabs(fib[p]-val),b=myabs(fib[p-1]-val); if(a==b) return p-1; else if(a<b) return p; else return p-1; } struct Segment_Tree { LL sum[MAXN],fibsum[MAXN]; int tar[MAXN]; void build(int o,int L,int R) { sum[o]=tar[o]=0; if(L==R) { fibsum[o]=fib[getPosofFib(0)]; return ; } int M=(L+R)/2; build(o<<1,L,M); build(o<<1|1,M+1,R); push_up(o); } void push_up(int o) { sum[o]=sum[o<<1]+sum[o<<1|1]; fibsum[o]=fibsum[o<<1]+fibsum[o<<1|1]; } void push_down(int o) { if(tar[o]) { tar[o<<1]=tar[o<<1|1]=tar[o]; sum[o<<1]=fibsum[o<<1]; sum[o<<1|1]=fibsum[o<<1|1]; tar[o]=0; } } void add(int o,int L,int R,int p,int c) { if(L==R) { sum[o]+=c; fibsum[o]=fib[getPosofFib(sum[o])]; } else { push_down(o); int M=(L+R)/2; if(p<=M) add(o<<1,L,M,p,c); else add(o<<1|1,M+1,R,p,c); push_up(o); } } void changeFib(int o,int L,int R,int ql,int qr) { if(ql<=L&&R<=qr) { sum[o]=fibsum[o]; tar[o]=1; } else { push_down(o); int M=(L+R)/2; if(ql<=M) changeFib(o<<1,L,M,ql,qr); if(M<qr) changeFib(o<<1|1,M+1,R,ql,qr); push_up(o); } } LL query(int o,int L,int R,int ql,int qr) { if(ql<=L&&R<=qr) return sum[o]; else { push_down(o); int M=(L+R)/2; LL s=0; if(ql<=M) s+=query(o<<1,L,M,ql,qr); if(M<qr) s+=query(o<<1|1,M+1,R,ql,qr); return s; } } }; Segment_Tree tree; int main() { init(); int n,m; while(scanf("%d%d",&n,&m)!=EOF) { tree.build(1,1,n); while(m--) { int p,a,b; scanf("%d%d%d",&p,&a,&b); if(p==1) tree.add(1,1,n,a,b); else if(p==2) printf("%I64d\n",tree.query(1,1,n,a,b)); else if(p==3) tree.changeFib(1,1,n,a,b); } } return 0; }