昨天做的时候,这题我第一次写的时候,代码刚写完电脑就卡死了,无奈之下只能重写了,可是重写之后一直WA,而且还找不出错误
今天早上终于找出错误了. 我在进行操作1更新的时候没有把sz初始化为0
so:
以后写线段树的区间更新WA的时候, 而且找不出错误的时候,去找一下sz 的pushdown操作和sz的初始化是否有错吧!!!!!!
题意:
给你N个元素,进行M次操作 1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000
操作1: 1 k d 表示k元素增加d, |d| < 231
操作2: 2 l r 查询区间[L,R]之间的元素的和
操作3: 3 l r 把区间[L,R ]之间的元素变成挨着最近的斐波拉契数
对每次查询,输出ans
方法:
节点里面包含一个l,r,sum,csum,sz
l,r表示区间范围
sum表示区间的元素的和
csum表示区间的元素全部变成斐波拉契数之后的和
sz表示该区间是否全为斐波拉契数
代码:
#include <cstdio>
#include <cstring>
#define maxn 100000
#define LL __int64
#define debug puts("hehe")
struct node
{
LL l, r;
LL sum, csum;
int sz;
}a[4*maxn+5];
LL F[100];
void Build(LL l, LL r, LL n)
{
a[n].l= l;
a[n].r= r;
a[n].sum= a[n].sz= 0;
if(a[n].l == a[n].r)
{
a[n].csum= 1;
return;
}
LL mid=(a[n].l + a[n].r)/ 2;
Build(l, mid, 2*n);
Build(mid+1, r, 2*n+1);
a[n].csum= a[2*n].csum + a[2*n+1].csum;
}
LL ff(LL num)
{
for(int i= 1; i< 100; i++)
if(F[i]>= num)
{
LL t1= F[i]- num;
LL t2= num- F[i-1];
if(t1< t2)
return F[i];
return F[i-1];
}
}
void pushdown(int n)
{
if(a[n].sz)
{
if(a[n].l== a[n].r)
a[n].sum= a[n].csum;
else
{
a[2*n].sz= a[2*n+1].sz= a[n].sz;
a[2*n].sum= a[2*n].csum;
a[2*n+1].sum= a[2*n+1].csum;
}
a[n].sz= 0;
}
}
void add(LL v, LL num, LL n)
{
if(a[n].l== v && a[n].r== v)
{
a[n].sum+= num;
a[n].csum= ff(a[n].sum);
a[n].sz= 0; // 这里没有清除标记一直wa
return;
}
pushdown(n);
int mid= (a[n].l + a[n].r)/ 2;
if(v<= mid)
add(v, num, 2*n);
else
add(v, num, 2*n+1);
a[n].sum= a[2*n].sum + a[2*n+1].sum;
a[n].csum= a[2*n].csum + a[2*n+1].csum;
}
LL Qsum(LL l, LL r, LL n)
{
if(a[n].l == l && a[n].r== r)
return a[n].sum;
pushdown(n);
int mid= (a[n].l + a[n].r)/ 2;
if(r<= mid)
return Qsum(l, r, 2*n);
else if(l> mid)
return Qsum(l, r, 2*n+1);
else
return Qsum(l, mid, 2*n)+ Qsum(mid+1, r, 2*n+1);
}
void update(LL l, LL r, LL n)
{
if(a[n].sz)
return;
if(a[n].l== l && a[n].r== r)
{
a[n].sum= a[n].csum;
a[n].sz=1;
return;
}
LL mid= (a[n].l + a[n].r)/2;
if(r<= mid)
update(l, r, 2*n);
else if(l> mid)
update(l, r, 2*n+1);
else
{
update(l, mid, 2*n);
update(mid+1, r, 2*n+1);
}
a[n].sum= a[2*n].sum + a[2*n+1].sum;
a[n].csum= a[2*n].csum + a[2*n+1].csum;
}
int main()
{
F[0]= F[1]= 1;
for(int i= 2; i< 100; i++)
F[i]= F[i-2] + F[i-1];
LL n, m;
freopen("C:/Users/Monkey/Desktop/in.txt","r",stdin);
while(scanf("%I64d %I64d",&n,&m)!=EOF)
{
Build(1, n, 1);
while(m--)
{
LL id, l, r;
scanf("%I64d %I64d %I64d",&id,&l,&r);
if(id== 1)
add(l, r, 1);
else if(id== 2)
printf("%I64d\n",Qsum(l, r, 1));
else
update(l, r, 1);
}
}
return 0;
}
/*
wa的原因
3 5
1 2 6
3 1 2
1 2 1
3 1 2
2 2 2
*/
//如果不清除根节点的sz,那么第二次更新该点之后,
//若进行操作3,因为改点的sz还是等于1.所以直接return了,该节点没有变成斐波拉契数