链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893
题意:给你一个长度n的数列,初始都为0。有三种操作,第一种给第k个位置的数加d。另外一种是查询区间 [l , r] 的总和。第三种是使区间 [l , r] 的值改为离它近期的那个斐波那契数的值。
我刚開始用sum数组存储节点的值。第三种操作是个区间更新,可是区间更新的值不一样。我就想当然的搜到最底部的节点来处理更新,果断T了。后来想了想。事实上能够在节点上再加一个信息。就是这个值下次进行第三种操作要变成的值,在每次进行第一种操作时进行这个值得更新,区间也一样存储下次变化后的总值。这样在进行第三种操作时就能够进行区间更新了比較省时。我不习惯用结构体写,所以多定义了一个数组。
sum数组存储正常值。fuck数组存储下次要变成的斐波那契值。col数组仅仅起标记作用。
事实上这题就是简单的单点更新和区间更新,合到了一起,我还是做的太少。没有在单点更新和区间查询中加pushdown,WA了两发。
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 100100 #define eps 1e-11 #define INF 0x7FFFFFFF #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 long long sum[MAXN<<2]; long long col[MAXN<<2]; long long fuck[MAXN<<2]; long long n,m; long long f[100]; void pushup(long long rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; fuck[rt] = fuck[rt<<1] + fuck[rt<<1|1]; } void pushdown(long long rt,long long m){ if(col[rt]){ col[rt<<1] = fuck[rt<<1]; col[rt<<1|1] = fuck[rt<<1|1]; sum[rt<<1] = fuck[rt<<1]; sum[rt<<1|1] = fuck[rt<<1|1]; col[rt] = 0; } } void build(long long l,long long r,long long rt){ col[rt] = 0; if(l==r){ sum[rt] = 0; fuck[rt] = 1; return ; } long long m = (l+r)>>1; build(lson); build(rson); pushup(rt); } void update(long long pos,long long add,long long l,long long r,long long rt){ if(l==r){ sum[rt] += add; long long p = lower_bound(f,f+90,sum[rt])-f; if(p-1>=0){ long long fp1 = f[p] - sum[rt]; if(fp1<0) fp1 = -fp1; long long fp2 = f[p-1] - sum[rt]; if(fp2<0) fp2 = -fp2; if(fp1>=fp2) fuck[rt] = f[p-1]; else fuck[rt] = f[p]; } else fuck[rt] = f[p]; return ; } pushdown(rt,r-l+1); long long m = (l+r)>>1; if(pos<=m) update(pos,add,lson); else update(pos,add,rson); pushup(rt); } void update2(long long L,long long R,long long l,long long r,long long rt){ if(L<=l&&r<=R){ col[rt] = fuck[rt]; sum[rt] = fuck[rt]; return ; } pushdown(rt,r-l+1); long long m = (l+r)>>1; if(L<=m) update2(L,R,lson); if(R>m) update2(L,R,rson); pushup(rt); } long long query(long long L,long long R,long long l,long long r,long long rt){ if(L<=l&&r<=R){ return sum[rt]; } pushdown(rt,rt-l+1); long long ans = 0; long long m = (l+r)>>1; if(L<=m) ans += query(L,R,lson); if(R>m) ans += query(L,R,rson); return ans; } int main(){ long long i,j,l,r,k,d,x; f[0] = 1; f[1] = 1; for(i=2;i<90;i++){ f[i] = f[i-1] + f[i-2]; } while(scanf("%I64d%I64d",&n,&m)!=EOF){ build(1,n,1); while(m--){ scanf("%I64d%I64d%I64d",&x,&l,&r); if(x==1){ update(l,r,1,n,1); } else if(x==2){ long long ans = query(l,r,1,n,1); printf("%I64d ",ans); } else{ update2(l,r,1,n,1); } } } return 0; }