zoukankan      html  css  js  c++  java
  • 值域线段树 bzoj 4627

         这是题目链接4627: [BeiJing2016]回转寿司

    题目大意:

    给定n个数,求有多少个字段和在 满足 L<=sum<=R;

    解题思路

    需要解这个题目,需要有线段树加可持续化的思想,但是这个题目只需要上一棵线段树的信息,所以可以不用主席树,只要用到值域线段树。那么,这样就可以把问题转化为:

    先处理处前缀和。 求 L<=sum[j]-sum[i]<=R (0 <=i < j<=n) 有多少个?

    那么我们可以用值域线段树搞一下,线段树节点存值的个数,每次把前缀和这个值插入,每次查询,原问题就等同于 当前线段树中有多少个值是在 [ sum[j]-R , sum[j]-L ] 这个区间,

    意思就是,每次把上一个前缀和插入需要计算一下上一棵线段树值在[ sum[j]-R , sum[j]-L ] 个数。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <vector>
     5 #include <iostream>
     6 using namespace std;
     7 
     8 typedef long long int LL;
     9 const LL INF=10000000000ll;
    10 const int maxn=100000*32;
    11 struct ACM
    12 {
    13     struct Node
    14     {
    15         LL val;
    16         int lson,rson;
    17     }seg[maxn];
    18     int sz;
    19     int newnode()
    20     {
    21         sz++;
    22         seg[sz].val=0;
    23         seg[sz].rson=-1;
    24         seg[sz].lson=-1;
    25         return sz;
    26     }
    27     void init()
    28     {
    29         sz=-1;
    30     }
    31     void update(int &root,LL l,LL r,LL val)
    32     {
    33         if(root==-1) root=newnode();
    34         seg[root].val++;
    35         if(l==r) return ;
    36         LL mid=(l+r)>>1;
    37         if(val<=mid) update(seg[root].lson,l,mid,val);
    38         else update(seg[root].rson,mid+1,r,val);
    39     }
    40     LL query(int root,LL l,LL r,LL ql,LL qr)
    41     {
    42         if(root==-1) return 0;
    43         if(l==ql&&r==qr) return seg[root].val;
    44         LL mid=(l+r)>>1;
    45         if(qr<=mid) return query(seg[root].lson,l,mid,ql,qr);
    46         else if(ql>mid) return query(seg[root].rson,mid+1,r,ql,qr);
    47         else return query(seg[root].lson,l,mid,ql,mid)+query(seg[root].rson,mid+1,r,mid+1,qr);
    48     }
    49     /**
    50     void debug(int i)
    51     {
    52         if(i==-1) return ;
    53         printf("node=%d val=%lld lson=%d rson=%d
    ",i,seg[i].val,seg[i].lson,seg[i].rson);
    54         debug(seg[i].lson),debug(seg[i].rson);
    55     }
    56     */
    57 }AC;
    58 
    59 int main()
    60 {
    61     int n,L,R,root=-1;
    62     scanf("%d%d%d",&n,&L,&R);
    63     LL sum=0,ans=0;
    64     AC.init();
    65     for(int i=1; i<=n; i++)
    66     {
    67         int num;
    68         scanf("%d",&num);
    69         AC.update(root,-INF,INF,sum);
    70         sum+=num;
    71         ans+=AC.query(root,-INF,INF,sum-R,sum-L);
    72     }
    73     printf("%lld
    ",ans);
    74     return 0;
    75 }
  • 相关阅读:
    《Java技术》第七次作业
    《Java技术》第六次作业
    《Java技术》第五次作业
    《Java技术》第四次作业
    《Java技术》第三次作业
    《Java技术》第二次作业
    《Java技术》第一次作业
    股票——布林带
    股票——指数移动平均线
    股票——简单移动平均线
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7207923.html
Copyright © 2011-2022 走看看