A - Wow! Such Sequence!——线段树+lazy
2015-01-23 19:22
471 查看
####
线段树+lazy操作
Recently, Doge got a funny birthday present from his new friend, Protein Tiger from St. Beeze College. No, not cactuses. It's a mysterious blackbox.
After some research, Doge found that the box is maintaining a sequence an of n numbers internally, initially all numbers are zero, and there are THREE "operations":
1.Add d to the k-th number of the sequence.
2.Query the sum of ai where l ≤ i ≤ r.
3.Change ai to the nearest Fibonacci number, where l ≤ i ≤ r.
4.Play sound "Chee-rio!", a bit useless.
Let F 0 = 1,F 1 = 1,Fibonacci number Fn is defined as F n = F n - 1 + F n - 2 for n ≥ 2.
Nearest Fibonacci number of number x means the smallest Fn where |F n - x| is also smallest.
Doge doesn't believe the machine could respond each request in less than 10ms. Help Doge figure out the reason.
Input
Input contains several test cases, please process till EOF.
For each test case, there will be one line containing two integers n, m.
Next m lines, each line indicates a query:
1 k d - "add"
2 l r - "query sum"
3 l r - "change to nearest Fibonacci"
1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, |d| < 2 31, all queries will be valid.
Output
For each Type 2 ("query sum") operation, output one line containing an integer represent the answer of this query.
[b]Sample Input
[/b]
1 1
2 1 1
5 4
1 1 7
1 3 17
3 2 4
2 1 5 Sample Output
022
#题意:这是一个线段树,给你n个节点,m次操作,每个节点的初始值为0,;当输入为1的时候对应位置节点加p。当输入为2的时候 ,查询区间总和。当输入为3的时候,节点替换为与他差值最小的FIB数列的值,差值相同的取小的那个:
题解:
这里我们维护两个值,sum1,sum2,前者表示当前值,后者表示与他对应的FIB数列的值。其他的基本上就是和线段树一样。但是注意这里我们要进行lazy操作不然不T则W;
注意这里我们要用—int64,不然要错;
#include<string.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<map>
using namespace std;
#define mx 100009
__int64 a[mx];
struct node
{
__int64 le,ri,sum1;
__int64 sum2;
__int64 flag;
} tree[mx*4];
__int64 find1(__int64 val)
{
__int64 ss=lower_bound(a,a+90,val)-a; //查找fib数列里的对应值
if(ss==0) return 1;
if(a[ss]!=val)
{
if((a[ss]-val)>=(val-a[ss-1]))
return a[ss-1];
else
return a[ss];
}
else return a[ss];
}
void pushup(__int64 id)
{
tree[id].sum1=tree[id*2].sum1+tree[id*2+1].sum1;
tree[id].sum2=tree[id*2].sum2+tree[id*2+1].sum2;
}
void pushdown(__int64 id)
{
if(tree[id].flag)
{
tree[id*2].sum1=tree[id*2].sum2;
tree[id*2+1].sum1=tree[id*2+1].sum2;
tree[id].flag=0;
tree[id*2+1].flag=tree[id*2].flag=1;
}
}
void buildtree(__int64 id,__int64 l,__int64 r)
{
tree[id].le=l;
tree[id].ri=r;
tree[id].flag=0;
if(l==r)
{
tree[id].sum2=1;
tree[id].sum1=0;
return ;
}
__int64 mid=(l+r)/2;
buildtree(id*2,l,mid);
buildtree(id*2+1,mid+1,r);
pushup(id);
}
void update1(__int64 id,__int64 pos,__int64 val)
{
if(tree[id].le==tree[id].ri)
{
tree[id].sum1+=val;
tree[id].sum2=find1(tree[id].sum1);
return ;
}
pushdown(id); //注意这里我们要向下更新,不然到时再累加操作的时候值没有更新的话就是错的,自己在想一下就想通了,主要是要考虑区间
__int64 mid=(tree[id].le+tree[id].ri)/2;
if(pos<=mid)
update1(id*2,pos,val);
else update1(id*2+1,pos,val);
pushup(id);
}
void update2(__int64 id,__int64 l,__int64 r)
{
if(tree[id].le>=l&&tree[id].ri<=r)
{
tree[id].sum1=tree[id].sum2;
tree[id].flag=1;
return ;
}
pushdown(id); //这里向下更新
__int64 mid=(tree[id].le+tree[id].ri)/2;
if(l<=mid)
update2(id*2,l,r);
if(r>mid) update2(id*2+1,l,r);
pushup(id);
}
__int64 ans;
void ask(__int64 id,__int64 l,__int64 r)
{
if(tree[id].le>=l&&tree[id].ri<=r)
{
ans+=tree[id].sum1;
return;
}
pushdown(id); //这里也是,我们要考虑区间,W了多次看了别人的代码,才发现这个错误,哎,太弱了
__int64 mid=(tree[id].le+tree[id].ri)/2;
if(l<=mid)
ask(id*2,l,r);
if(mid<r)
ask(id*2+1,l,r);
}
int main()
{
__int64 n,m,i,j;
__int64 l,r;
__int64 gg;
while(scanf("%I64d %I64d",&n,&m)!=EOF)
{
buildtree(1,1,n);
a[1]=a[0]=1;
for(i=2; i<=90; i++)
{
a[i]=a[i-1]+a[i-2];
}
while(m--)
{
scanf("%I64d %I64d %I64d",&gg,&l,&r);
if(gg==1)
{
update1(1,l,r);
}
else if(gg==2)
{
ans=0;
ask(1,l,r);
printf("%I64d\n",ans);
}
else if(gg==3)
{
update2(1,l,r);
}
}
}
return 0;
}
线段树+lazy操作
Recently, Doge got a funny birthday present from his new friend, Protein Tiger from St. Beeze College. No, not cactuses. It's a mysterious blackbox.
After some research, Doge found that the box is maintaining a sequence an of n numbers internally, initially all numbers are zero, and there are THREE "operations":
1.Add d to the k-th number of the sequence.
2.Query the sum of ai where l ≤ i ≤ r.
3.Change ai to the nearest Fibonacci number, where l ≤ i ≤ r.
4.Play sound "Chee-rio!", a bit useless.
Let F 0 = 1,F 1 = 1,Fibonacci number Fn is defined as F n = F n - 1 + F n - 2 for n ≥ 2.
Nearest Fibonacci number of number x means the smallest Fn where |F n - x| is also smallest.
Doge doesn't believe the machine could respond each request in less than 10ms. Help Doge figure out the reason.
Input
Input contains several test cases, please process till EOF.
For each test case, there will be one line containing two integers n, m.
Next m lines, each line indicates a query:
1 k d - "add"
2 l r - "query sum"
3 l r - "change to nearest Fibonacci"
1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, |d| < 2 31, all queries will be valid.
Output
For each Type 2 ("query sum") operation, output one line containing an integer represent the answer of this query.
[b]Sample Input
[/b]
1 1
2 1 1
5 4
1 1 7
1 3 17
3 2 4
2 1 5 Sample Output
022
#题意:这是一个线段树,给你n个节点,m次操作,每个节点的初始值为0,;当输入为1的时候对应位置节点加p。当输入为2的时候 ,查询区间总和。当输入为3的时候,节点替换为与他差值最小的FIB数列的值,差值相同的取小的那个:
题解:
这里我们维护两个值,sum1,sum2,前者表示当前值,后者表示与他对应的FIB数列的值。其他的基本上就是和线段树一样。但是注意这里我们要进行lazy操作不然不T则W;
注意这里我们要用—int64,不然要错;
#include<string.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<map>
using namespace std;
#define mx 100009
__int64 a[mx];
struct node
{
__int64 le,ri,sum1;
__int64 sum2;
__int64 flag;
} tree[mx*4];
__int64 find1(__int64 val)
{
__int64 ss=lower_bound(a,a+90,val)-a; //查找fib数列里的对应值
if(ss==0) return 1;
if(a[ss]!=val)
{
if((a[ss]-val)>=(val-a[ss-1]))
return a[ss-1];
else
return a[ss];
}
else return a[ss];
}
void pushup(__int64 id)
{
tree[id].sum1=tree[id*2].sum1+tree[id*2+1].sum1;
tree[id].sum2=tree[id*2].sum2+tree[id*2+1].sum2;
}
void pushdown(__int64 id)
{
if(tree[id].flag)
{
tree[id*2].sum1=tree[id*2].sum2;
tree[id*2+1].sum1=tree[id*2+1].sum2;
tree[id].flag=0;
tree[id*2+1].flag=tree[id*2].flag=1;
}
}
void buildtree(__int64 id,__int64 l,__int64 r)
{
tree[id].le=l;
tree[id].ri=r;
tree[id].flag=0;
if(l==r)
{
tree[id].sum2=1;
tree[id].sum1=0;
return ;
}
__int64 mid=(l+r)/2;
buildtree(id*2,l,mid);
buildtree(id*2+1,mid+1,r);
pushup(id);
}
void update1(__int64 id,__int64 pos,__int64 val)
{
if(tree[id].le==tree[id].ri)
{
tree[id].sum1+=val;
tree[id].sum2=find1(tree[id].sum1);
return ;
}
pushdown(id); //注意这里我们要向下更新,不然到时再累加操作的时候值没有更新的话就是错的,自己在想一下就想通了,主要是要考虑区间
__int64 mid=(tree[id].le+tree[id].ri)/2;
if(pos<=mid)
update1(id*2,pos,val);
else update1(id*2+1,pos,val);
pushup(id);
}
void update2(__int64 id,__int64 l,__int64 r)
{
if(tree[id].le>=l&&tree[id].ri<=r)
{
tree[id].sum1=tree[id].sum2;
tree[id].flag=1;
return ;
}
pushdown(id); //这里向下更新
__int64 mid=(tree[id].le+tree[id].ri)/2;
if(l<=mid)
update2(id*2,l,r);
if(r>mid) update2(id*2+1,l,r);
pushup(id);
}
__int64 ans;
void ask(__int64 id,__int64 l,__int64 r)
{
if(tree[id].le>=l&&tree[id].ri<=r)
{
ans+=tree[id].sum1;
return;
}
pushdown(id); //这里也是,我们要考虑区间,W了多次看了别人的代码,才发现这个错误,哎,太弱了
__int64 mid=(tree[id].le+tree[id].ri)/2;
if(l<=mid)
ask(id*2,l,r);
if(mid<r)
ask(id*2+1,l,r);
}
int main()
{
__int64 n,m,i,j;
__int64 l,r;
__int64 gg;
while(scanf("%I64d %I64d",&n,&m)!=EOF)
{
buildtree(1,1,n);
a[1]=a[0]=1;
for(i=2; i<=90; i++)
{
a[i]=a[i-1]+a[i-2];
}
while(m--)
{
scanf("%I64d %I64d %I64d",&gg,&l,&r);
if(gg==1)
{
update1(1,l,r);
}
else if(gg==2)
{
ans=0;
ask(1,l,r);
printf("%I64d\n",ans);
}
else if(gg==3)
{
update2(1,l,r);
}
}
}
return 0;
}
相关文章推荐
- HDU4893--Wow! Such Sequence! (线段树 延迟标记)
- HDU 4893 Wow! Such Sequence!【线段树】
- HDU 4893 Wow! Such Sequence! 水线段树
- HDOJ 4893 Wow! Such Sequence!
- HDU 4893(Wow! Such Sequence!-线段树单点修改+区间求和+改为最近Fib数)
- 【线段树】 HDOJ 4893 Wow! Such Sequence!
- 【2014 Multi-University Training Contest 3 1007】/【HDU 4893】 Wow! Such Sequence!
- hdu4893 Wow! Such Sequence!
- Wow! Such Sequence! (线段树) hdu4893
- 【2014 Multi-University Training Contest 3 1007】/【HDU 4893】 Wow! Such Sequence!
- hdu 4893 Wow! Such Sequence!
- 线段树 + 区间更新: HDU 4893 Wow! Such Sequence!
- HDU 4893 Wow! Such Sequence! 线段树
- HDU 4893 Wow! Such Sequence!
- HDOJ 4893 Wow! Such Sequence! 线段树
- hdu 4893 Wow! Such Sequence! 线段树单点更新+区间更新+区间查询
- 【HDU】4893 Wow! Such Sequence! 线段树
- hdu 4893 Wow! Such Sequence! 2014 Multi-University Training Contest 3
- hdu 4893 Wow! Such Sequence!
- HDU 4893 Wow! Such Sequence! (线段树)