http://acm.hdu.edu.cn/showproblem.php?pid=4893
题意就是 完成线段树的几种高端操作
操作如下:
1。 单点修改
2。 区间求和,并输出结果
3。 区间修改。PS: 这里要求把L~R区间内的所有值都变为最接近的那个斐波那契数0 0
这里我说下操作3吧,操作1和2 基础操作。
在这里,我们运用一种 叫做伴随树的东西,即每次线段树操作时 操作2课线段树,第一颗 就是正常的线段树,第二颗是 维护每个节点最接近的斐波那契数的值。 之后在设置一个标记数组,记录每个节点是否被覆盖。如果没有覆盖则覆盖。之后向下传标记。
具体看看代码
#include <bits/stdc++.h>
#define mme(i,j) memset(i,j,sizeof(i))
#define maxs 2002020
using namespace std;
long long fib[220];
long long seg[maxs],seg2[maxs];
bool flag[maxs];
void setfib(){
fib[0]=fib[1]=1;
for(int i=2; i<=105; i++)
fib[i] = fib[i-1] + fib[i-2];
}
void pushUp(int rt)
{
seg[rt]=seg[rt<<1]+seg[rt<<1|1];
seg2[rt]=seg2[rt<<1]+seg2[rt<<1|1];
}
void pushDown(int rt) {
if(flag[rt]){
flag[ rt<<1 ] = flag[ rt<<1|1 ] =1;
seg[ rt<<1 ] = seg2[ rt<<1 ];
seg[ rt<<1|1 ] = seg2[ rt<<1|1 ];
flag[rt]=0;
}
}
long long getfib(long long x){
int pos = lower_bound(fib,fib+105,x)-fib;
if( pos == 0 )
return 1;
return abs( fib[pos]-x ) >= abs( x-fib[pos-1] ) ? fib[pos-1]:fib[pos];
}
void build(int l,int r,int rt)
{
if(l==r)
{
seg[rt]=0;
seg2[rt]=1;
flag[rt]=0;
return;
}
else{
int m=( l + r )>>1;
build( l , m , rt<<1 );
build( m + 1 , r , rt<<1|1 );
pushUp( rt );
}
}
void updatepos(int p,int k,int l,int r,int rt){
if(l==r){
seg[rt]+=k;
seg2[rt]=getfib(seg[rt]);
flag[rt]=0;
return;
}
pushDown(rt);
int m=(l+r)>>1;
if( p<=m ) updatepos(p,k,l,m,rt<<1);
else updatepos(p,k,m+1,r,rt<<1|1);
pushUp(rt);
}
long long ans=0;
void updateseg(int al,int ar,int l,int r,int rt)
{
if(al<=l && ar>=r){
seg[rt]=seg2[rt];
flag[rt]=1;
return;
}
pushDown(rt);
int m=(l+r)>>1;
if(al<=m)
updateseg(al,ar,l,m,rt<<1);
if(m<ar)
updateseg(al,ar,m+1,r,rt<<1|1);
pushUp(rt);
}
void query(int al,int ar,int l,int r,int rt) {
if( al <= l && ar >= r ){
if(flag[rt])
ans+=seg2[rt];
else
ans+=seg[rt];
return;
}
pushDown(rt);
int m = (l+r)>>1;
if(al<=m)
query(al,ar,l,m,rt<<1);
if(m<ar)
query(al,ar,m+1,r,rt<<1|1);
}
int main()
{
int n,m;
setfib();
while(~scanf("%d%d",&n,&m)){
mme(seg,0);
mme(seg2,0);
mme(flag,0);
build(1,n,1);
int op,x,y;
while(m--){
scanf("%d%d%d",&op,&x,&y);
if(op==1)
updatepos(x,y,1,n,1);
else if( op == 2){
ans=0;
query(x,y,1,n,1);
cout<<ans<<endl;
}
else if(op==3)
updateseg(x,y,1,n,1);
}
}
return 0;
}
/*
1 1
2 1 1
5 4
1 1 7
1 3 17
3 2 4
2 1 5
*/