hdoj 4893 2014年多校联合3 1007

来源:互联网 发布:知乎美国大选 编辑:程序博客网 时间:2024/04/30 04:57

这道题可以说是标准的线段树的用法,单点更新+区间查询和修改。

不过这里有一个提前要做的工作,那就是每次单点更新的时候也要更新区间。否则的话,区间更新的时候,就得更新到叶子节点,复杂度就成了O(n)了。

那么怎么才能不更新到叶子节点呢,就是加一个标记,表示离它最近的斐波那契数列数。这样每次更新的时候,直接把斐波那契数赋值给sum就可以了。

单点更新的时候,才把标记一层一层的传递下去。

具体看代码吧。不过不知道为什么,C++ 一直WA,G++过了。表示很诧异。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxn 111111using namespace std;struct Node{int l,r,c;  //c是标记,表示这个区间或点要变成最近的斐波那契数__int64 sum,fsum;  //sum是区间和,fsum是区间的斐波那契数的和};Node node[maxn*4];__int64 f[100];void init(){    int i;    f[0]=f[1]=1;    for(i=2;i<93;i++)        f[i]=f[i-1]+f[i-2];}void pushup(int k)   //向上更新{    node[k].sum=node[k*2].sum+node[k*2+1].sum;node[k].fsum=node[k*2].fsum+node[k*2+1].fsum;}void pushdown(int k)   //向下传递{    if(node[k].l==node[k].r) return ;    if(node[k].c)    {        node[k*2].c=node[k*2+1].c=1;        node[k*2].sum=node[k*2].fsum;        node[k*2+1].sum=node[k*2+1].fsum;        node[k].c=0;    }}void build_tree(int l,int r,int k)           //建树{node[k].l=l;node[k].r=r;node[k].sum=0;node[k].c=0;node[k].fsum=1;if(l==r)return ;int m=(l+r)/2;build_tree(l,m,k*2);build_tree(m+1,r,k*2+1);pushup(k);}void Insert(int k,int num,int d)  //单点更新,顺便更新最近的斐波那契数。这样才能为操作3省时。{     pushdown(k);    if(node[k].l==node[k].r)    {         node[k].sum+=d;         int i=lower_bound(f,f+93,node[k].sum)-f;         if(i && abs(f[i]-node[k].sum)>=abs(f[i-1]-node[k].sum))            i=i-1;         node[k].fsum=f[i];         return ;    }    int m=(node[k].l+node[k].r)/2;    if(num<=m)        Insert(k*2,num,d);    else Insert(k*2+1,num,d);    pushup(k);}void change(int k,int l,int r)  //区间更新,打完标记就返回,不要更新到叶子节点。{    if(node[k].l>r||node[k].r<l)        return ;    if(l<=node[k].l&&node[k].r<=r)    {node[k].c=1;node[k].sum=node[k].fsum;return ;}    pushdown(k);    change(k*2,l,r);    change(k*2+1,l,r);    pushup(k);}long long check(int k,int l,int r)  //查询操作{    pushdown(k);    if(node[k].l>r||node[k].r<l)        return 0;    if(l<=node[k].l&&node[k].r<=r)    {        return node[k].sum;    }    return check(k*2,l,r)+check(k*2+1,l,r);}int main(){    //freopen("1007.in","r",stdin);    //freopen("1007.out","w",stdout);int i,j,k,op;int n,m,d,l,r;init();while(scanf("%d%d",&n,&m)!=EOF)    {        build_tree(1,n,1);        for(i=0;i<m;i++)        {            scanf("%d",&op);            if(op==1)            {                scanf("%d%d",&k,&d);                Insert(1,k,d);            }            else if(op==3)            {                scanf("%d%d",&l,&r);                change(1,l,r);            }            else            {                scanf("%d%d",&l,&r);                printf("%I64d\n",check(1,l,r));            }        }    }return 0;}


 

0 0
原创粉丝点击