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;
}