• codevs2492上帝造题的七分钟 2(线段树)


    /*
    区间修改 区间查询 可以用线段树搞
    但是一般的标记下放对这个题好像不合适 
    只能改叶子 然后更新父亲(虽然跑的有点慢)
    小优化:如果某个点是1 就不用再开方了
    所以搞一个f[i]标记 i 这个点还需不需要处理下去 
    注意用longlong 还有就是数组开大 
    */
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #define LL long long
    #define maxn 500010
    using namespace std;
    LL n,m,num,x,y,z;
    LL a[maxn],f[maxn];
    struct node
    {
        LL o;
        LL l,r;
        LL lc,rc;
        LL sum;
    }t[maxn*2];
    LL init()
    {
        LL x=0;
        char s;
        bool f=0;
        s=getchar();
        while(s<'0'||s>'9')
          {
              if(s=='-')f=1;
              s=getchar();
          }
        while(s>='0'&&s<='9')
          {
              x=x*10+s-'0';
              s=getchar();
          }
        if(f==0)return x;
        else return -x;
    }
    void Build(LL ll,LL rr)
    {
        LL k=++num;
        t[k].o=k;
        t[k].l=ll;t[k].r=rr;
        if(ll!=rr-1)
          {
              t[k].lc=num+1;
              Build(ll,(ll+rr)/2);
              t[k].rc=num+1;
              Build((ll+rr)/2,rr);
              t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
          }
        else t[k].sum=a[ll];
    }
    void update(LL k,LL ll,LL rr)
    {    
        if(f[k])return;//如果是1 说明儿子(如果有的话)要么是1 要么是0 不需要处理 直接返回 
        if(ll==rr-1)
          {
              t[k].sum=sqrt(t[k].sum);
              if(t[k].sum==1)f[k]=1;
              return;
          }
        LL mid=(ll+rr)/2;
        if(y<mid)update(t[k].lc,ll,(ll+rr)/2);
        if(z>=mid)update(t[k].rc,(ll+rr)/2,rr);
        t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
        f[k]=f[t[k].lc]&&f[t[k].rc];//如果左右儿子都是1 那么父亲点也不用更新了. 
    }
    LL find(LL k,LL ll,LL rr)
    {
        if(ll<=t[k].l&&rr>=t[k].r)return t[k].sum;
        LL ans=0;
        if(ll<(t[k].l+t[k].r)/2)ans+=find(t[k].lc,ll,rr);
        if(rr>(t[k].l+t[k].r)/2)ans+=find(t[k].rc,ll,rr);
        t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum;
        return ans;
    }
    int main()
    {
        n=init();
        for(int i=1;i<=n;i++)
          a[i]=init();
        Build(1,n+1);
        m=init();
        for(LL i=1;i<=m;i++)
          {
              x=init();
              y=init();
              z=init();
              if(y>z)swap(y,z);
              if(x==0)update(1,1,n+1);
              if(x==1)printf("%lld
    ",find(1,y,z+1));
          }
    }
  • 相关阅读:
    [leetcode] 110. 平衡二叉树
    [leetcode] 109. 有序链表转换二叉搜索树
    [leetcode] 108. 将有序数组转换为二叉搜索树
    [leetcode] 107. 二叉树的层次遍历 II
    [leetcode] 106. 从中序与后序遍历序列构造二叉树
    [leetcode] 105. 从前序与中序遍历序列构造二叉树
    [leetcode] 111. 二叉树的最小深度
    LeetCode
    LeetCode
    LeetCode
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5463514.html
Copyright © 2020-2023  润新知