Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2234 Accepted Submission(s): 657
【题目分析】
这题相比于裸的线段树区间更新有了一些难度。
我们在每个结点中设一个fib,表示离sum最近的fibnacci数,每次区间更新时,就将sum的值更新为fib。fib的值只有在单点更新的过程中才会改变,也就是说当sum值改变的时候fib才改变,因为当sum变为fib后,离sum最近的fibnacci数还是fib值。
lazy----记录该点以下的孩子结点是否需要更新。
我用long long ,然后用了%lld输入,不知道杭电不支持%lld,debug了半天,TLE了20多次,后来改%lld为%I64d就过了,哭死QAQ...
//Memory Time // K MS #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack> #include<iomanip> #include<string> #include<climits> #include<cmath> #define MAX 100010 #define LL long long using namespace std; LL n,m; LL ans; LL f[60]; struct Tree { LL l,r; LL sum,fib; bool lazy; }; Tree tree[MAX*3]; LL Find(LL x) { if(x<=0)return 1; LL ldis,rdis; for(int i=0;i<59;++i) { if(f[i]<=x&&f[i+1]>=x) { ldis=x-f[i]; rdis=f[i+1]-x; return ldis<=rdis?f[i]:f[i+1]; } } } void pushup(LL x) { LL tmp=x<<1; tree[x].sum=tree[tmp].sum+tree[tmp+1].sum; tree[x].fib=tree[tmp].fib+tree[tmp+1].fib; } void pushdown(LL x) { if(!tree[x].lazy)return; tree[x].lazy=0; if(tree[x].l==tree[x].r)return; LL tmp=x<<1; tree[tmp].lazy=tree[tmp+1].lazy=1; tree[tmp].sum=tree[tmp].fib; tree[tmp+1].sum=tree[tmp+1].fib; } void build(LL l,LL r,LL x) { tree[x].l=l,tree[x].r=r; tree[x].sum=0,tree[x].fib=1,tree[x].lazy=0; if(l==r)return; LL tmp=x<<1; LL mid=(l+r)>>1; build(l,mid,tmp); build(mid+1,r,tmp+1); pushup(x); } void add(LL x,LL k,LL num) { if(tree[x].l==tree[x].r) { tree[x].sum+=num; tree[x].fib=Find(tree[x].sum); return; } if(tree[x].lazy) pushdown(x); LL tmp=x<<1; LL mid=(tree[x].l+tree[x].r)>>1; if(k<=mid) add(tmp,k,num); else if(k>mid) add(tmp+1,k,num); pushup(x); } void change(LL l,LL r,LL x) { if(r<tree[x].l||l>tree[x].r)return; if(l<=tree[x].l&&r>=tree[x].r) { tree[x].sum=tree[x].fib; tree[x].lazy=1; return; } if(tree[x].lazy)pushdown(x); LL tmp=x<<1; LL mid=(tree[x].l+tree[x].r)>>1; if(r<=mid) change(l,r,tmp); else if(l>mid) change(l,r,tmp+1); else { change(l,mid,tmp); change(mid+1,r,tmp+1); } pushup(x); } void query(LL l,LL r,LL x) { if(r<tree[x].l||l>tree[x].r)return; if(l<=tree[x].l&&r>=tree[x].r) { ans+=tree[x].sum; return; } if(tree[x].lazy) pushdown(x); LL tmp=x<<1; LL mid=(tree[x].l+tree[x].r)>>1; if(r<=mid) query(l,r,tmp); else if(l>mid) query(l,r,tmp+1); else { query(l,mid,tmp); query(mid+1,r,tmp+1); } pushup(x); } int main() { // freopen("cin.txt","r",stdin); // freopen("cout.txt","w",stdout); f[0]=f[1]=1; for(int i=2;i<60;++i) f[i]=f[i-1]+f[i-2]; while(scanf("%I64d %I64d",&n,&m)!=EOF) { build(1,n,1); LL a,b,c; while(m--) { scanf("%I64d %I64d %I64d",&a,&b,&c); if(a==1) add(1,b,c); else if(a==2) { ans=0; query(b,c,1); printf("%I64d\n",ans); } else change(b,c,1); } } return 0; }