Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) |
一道区间线段树更新. 用了set 的二分. 找过一次最近斐波那契数. 就可以laz标记掉 下次不再更新. 否则会超时.
#include<stdio.h> #include<set> #define int64 __int64 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; int64 f[10000]; const int maxn=200000; set<int64> ss; struct node { int64 l,r; bool laz; //laz==0 代表需要更新 斐波那契. laz==1 代表不用更新斐波那契操作 也就是当节点的laz==1他和他的子孙第三种操作可以忽略. int64 sum; int64 mid() { return (l+r)/2; } }; struct node tree[maxn<<2]; void PushUp(int64 rt) { if(tree[rt<<1].laz && tree[rt<<1|1].laz)//如果两个儿子都不用更新斐波那契, 那父节点也不用 tree[rt].laz = 1; else tree[rt].laz = 0; } void getf()//算斐波那契数 存入f数组 { int i; f[0]=1,f[1]=1; ss.insert(f[0]); ss.insert(f[1]); for(i=2;i<=73;i++) { f[i]=f[i-1]+f[i-2]; ss.insert(f[i]); } } void build(int64 l,int64 r,int64 rt)//建树 { tree[rt].l=l; tree[rt].r=r; tree[rt].laz=0; if(tree[rt].l==tree[rt].r) { tree[rt].sum=0; return ; } int64 m=tree[rt].mid(); build(lson); build(rson); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void updata(int64 p,int64 add,int64 rt) { if(tree[rt].l==tree[rt].r)//单点更新, { tree[rt].laz=0;//如果更新了 那么就又需要重新寻找最近的斐波那契数 tree[rt].sum+=add; return ; } int64 m=tree[rt].mid(); if(p<=m) updata(p,add,rt<<1); else updata(p,add,rt<<1|1); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//更新sum PushUp(rt);//更新laz } void updata2(int64 L,int64 R,int64 rt) //3操作 更新到最近的斐波那契数 { if(tree[rt].laz==1) return; if(tree[rt].l==tree[rt].r) { tree[rt].laz=1;//该节点已经更新到最近斐波那契数,以后不再更新 //二分查找最近的斐波那契数. int64 l,r; set<int64>::iterator it1,it2; it2=it1=ss.lower_bound(tree[rt].sum); l=*it2; if(it1!=ss.begin()) it1--; r=*it1; tree[rt].sum=(tree[rt].sum-*it1)> ((*it2)-tree[rt].sum)?l:r; return ; } int64 m=tree[rt].mid(); if (L <= m) updata2(L , R , rt<<1); if (m < R) updata2(L , R , rt<<1|1); PushUp(rt); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } int64 query(int64 L,int64 R,int64 rt) { if(L<=tree[rt].l && tree[rt].r<=R) { return tree[rt].sum; } int64 m=tree[rt].mid(); int64 ret=0; if(R<=m) ret+=query(L,R,rt<<1); else if(L>m) ret+=query(L,R,rt<<1|1); else { ret+=query(L,R,rt<<1); ret+=query(L,R,rt<<1|1); } return ret; } int main() { int64 a,b,c; int64 op,i; int64 n,m; ss.clear(); getf(); while(scanf("%I64d %I64d",&n,&m)!=EOF) { build(1,n,1); while(m--) { scanf("%I64d",&op); if(op==2) { scanf("%I64d %I64d",&a,&b); printf("%I64d\n",query(a,b,1)); } else if(op==1) { scanf("%I64d %I64d",&a,&b); updata(a,b,1); } else if(op==3)//f { scanf("%I64d %I64d",&a,&b); updata2(a,b,1); } } } return 0; }