• [BZOJ4627][BeiJing2016]回转寿司(线段树)


    从左到右处理,设到当前数R的前缀和为cnt[i],则以i为右端点的合法的区间左端点j必然是L<=cnt[i]-cnt[j-1]<=R,即cnt[i]-R<=cnt[j-1]<=cnt[i]-L。

    问题相当于每次单点在cnt[i]处计数器加1,然后区间询问[cnt[i]-R,cnt[i]-L]中的数之和,动态开点线段树即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define lson ls[x],L,mid
     6 #define rson rs[x],mid+1,R
     7 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     8 typedef long long ll;
     9 using namespace std;
    10 
    11 const int N=5000100;
    12 const ll inf=1e12;
    13 ll cnt,res,ans,n,rt,lp,rp,nd,x,sm[N],ls[N],rs[N];
    14 
    15 void mdf(ll &x,ll L,ll R,ll pos){
    16     if (!x) x=++nd;
    17     if (L==R){ sm[x]++; return; }
    18     ll mid=(L+R)>>1;
    19     if (pos<=mid) mdf(lson,pos); else mdf(rson,pos);
    20     sm[x]=sm[ls[x]]+sm[rs[x]];
    21 }
    22 
    23 ll que(ll x,ll L,ll R,ll l,ll r){
    24     if (!x) return 0;
    25     if (L==l && r==R) return sm[x];
    26     ll mid=(L+R)>>1;
    27     if (r<=mid) return que(lson,l,r);
    28     else if (l>mid) return que(rson,l,r);
    29         else return que(lson,l,mid)+que(rson,mid+1,r);
    30 }
    31 
    32 int main(){
    33     freopen("bzoj4627.in","r",stdin);
    34     freopen("bzoj4627.out","w",stdout);
    35     scanf("%lld%lld%lld",&n,&lp,&rp); mdf(rt,-inf,inf,0);
    36     rep(i,1,n){
    37         scanf("%lld",&x); cnt+=x; ll res=que(rt,-inf,inf,cnt-rp,cnt-lp);
    38         ans+=res; mdf(rt,-inf,inf,cnt);
    39     }
    40     printf("%lld
    ",ans);
    41     return 0;
    42 }
  • 相关阅读:
    hdu 1003 dp最大子序列和
    模拟题 (+queue队列知识)
    hdu 1016 DFS
    OSGi 系列(二)之 Hello World
    OSGi 系列(一)之什么是 OSGi :Java 语言的动态模块系统
    Mina 系列(四)之KeepAliveFilter -- 心跳检测
    Mina 系列(三)之自定义编解码器.md
    Mina 系列(二)之基础
    Mina 快速入门
    Java 8 Optional 类深度解析
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9981066.html
Copyright © 2020-2023  润新知