zoukankan      html  css  js  c++  java
  • #cdq分治,树状数组#洛谷 5459 [BJOI2016]回转寿司

    题目

    [sum_{i=1}^nsum_{j=i}^{n}[Lleq sum_{k=i}^j a_kleq R] ]


    分析(树状数组)

    考虑前缀和,改为是否有两个数的差在([Lsim R])范围内,
    显然可以用树状数组做,记录(a_i,a_i-L,a_i-R),离散化


    代码(树状数组)

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    typedef long long lll;
    const int N=100011;
    lll a[N],b[N*3],ans;
    int c[N*3],n,L,R,Tot;
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    inline void update(int x){for (;x<=Tot;x+=-x&x) ++c[x];}
    inline signed query(int l,int r){
    	rr int ans=0; --l;
    	for (;r>l;r-=-r&r) ans+=c[r];
    	for (;l>r;l-=-l&l) ans-=c[l];
    	return ans;
    }
    signed main(){
    	n=iut(),L=iut(),R=iut(),Tot=1;
    	for (rr int i=1;i<=n;++i){
    		a[i]=a[i-1]+iut(),b[++Tot]=a[i],
    		b[++Tot]=a[i]-L,b[++Tot]=a[i]-R;
    	}
    	sort(b+1,b+1+Tot),Tot=unique(b+1,b+1+Tot)-b-1;
    	update(lower_bound(b+1,b+1+Tot,0)-b);
    	for (rr int i=1;i<=n;++i){
    		rr int fi=lower_bound(b+1,b+1+Tot,a[i]-R)-b,
    		       se=lower_bound(b+1,b+1+Tot,a[i]-L)-b,
    			   th=lower_bound(b+1,b+1+Tot,a[i])-b;
    		ans+=query(fi,se);
    		update(th); 
    	}
    	return !printf("%lld",ans);
    }
    

    分析(cdq分治)

    同理可以在cdq分治中用双指针找到(a_i-R,a_i-L)的位置,然后统计答案


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    typedef long long lll;
    const int N=100011;
    lll a[N],n,ans,b[N],L,R;
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    inline void cdq(int l,int r){
    	if (l==r) return;
    	rr int mid=(l+r)>>1;
    	cdq(l,mid),cdq(mid+1,r);
    	for (rr int i=mid+1,hl=l,hr=l-1;i<=r;++i){
    		while (hr<mid&&a[i]-L>=a[hr+1]) ++hr;//使刚好a[hr+1]>a[i]-L
    		while (hl<=mid&&a[i]-R>a[hl]) ++hl;//使a[hl]>=a[i]-R
    		ans+=hr-hl+1;//为什么不会出现负数,因为首先a[i]-L>=a[i]-R,所以hr-hl>=-1,加上1正好抵消掉
    	}
    	rr int i1=l,j1=mid+1,tot=0;
    	while (i1<=mid&&j1<=r)
    	if (a[i1]<=a[j1]) b[++tot]=a[i1],++i1;
    	    else b[++tot]=a[j1],++j1;
    	while (i1<=mid) b[++tot]=a[i1],++i1;
    	while (j1<=r) b[++tot]=a[j1],++j1;
    	for (rr int i=1;i<=tot;++i) a[l+i-1]=b[i];
    }
    signed main(){
    	n=iut(),L=iut(),R=iut();
    	for (rr int i=1;i<=n;++i) a[i]=a[i-1]+iut();
    	cdq(0,n);//a[0]也需要算进去
    	return !printf("%lld",ans);
    }
    
  • 相关阅读:
    SVN如何切换用户对代码进行操作
    SVN更新的时候报断言失败解决办法
    根据身份证号判断性别
    4.UiCollection API 详细介绍
    1.UiDevice API 详细介绍
    安卓常见反破解方式
    腾讯应用加固的脱壳分析和修复
    1.Android JUnit Runner(使用AndroidStudio)
    Java图形化界面设计——布局管理器之null布局(空布局)
    Java图形化界面设计——布局管理器之CardLayout(卡片布局)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13532969.html
Copyright © 2011-2022 走看看