【BZOJ】4627 [BeiJing2016]回转寿司

博客介绍了如何解决BZOJ 4627,即回转寿司的问题。首先通过计算前缀和,将问题转化为查找Sj-Si在[L, R]区间内的子序列数量。接着,博主提出了一个问题的变形,对于每个Sj,需要找出有多少Si位于[Sj-R, Sj-L]之间。文中提到了使用值域线段树作为解决方案,并补充了CDQ分治法的应用。" 118721544,11229415,Java现状:为何有人说它要凉了?,"['Java开发', '编程语言', '服务器开发', '职业发展', '编程学习']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4627

首先求一个前缀和,问题转化为计数 SjSi[L,R](i<j)
变形求对于每个 Sj ,求有多少 Si[SjR,SjL](i<j)
做法很多,我用了值域线段树。

#include<stdio.h>
#define cll const ll &
#define cint const int &
#define M 2333333
#define N 100005
#define inf 10000000005LL

typedef long long ll;

int tot,n,l,r,rt;
ll ans,a,la,L,R;

struct node{int k,l,r;}t[M];

void ins(int &k,cll l,cll r)
{
    if (k==0) k=++tot;
    t[k].k++;
    if (l==r) return;
    ll mid=l+r>>1;
    if (L<=mid){ins(t[k].l,l,mid);return;}
    ins(t[k].r,mid+1,r);
}

void find(cint k,cll l,cll r)
{
    if (!k) return;
    if (L<=l && r<=R)
    {
        ans+=t[k].k;
        return;
    }
    ll mid=l+r>>1;
    if (L<=mid) find(t[k].l,l,mid);
    if (mid<R) find(t[k].r,mid+1,r);
}

int main()
{
    scanf("%d%d%d",&n,&l,&r);
    ins(rt,-inf,inf);
    for (int i=1;i<=n;i++)
    {
        scanf("%lld",&a),a+=la;
        L=a-r,R=a-l;find(1,-inf,inf);
        L=a;ins(rt,-inf,inf);
        la=a;
    }
    printf("%lld",ans);
}

补一个CDQ分治

#include<stdio.h>
#include<algorithm>
#define cint const int &

typedef long long ll;
ll a[100050],ans;
int n,L,R;

void solve(cint l,cint r)
{
    if (r<=l) return;
    int mid=l+r>>1;
    solve(l,mid);solve(mid+1,r);
    int s=l,e=l-1;
    for (int i=mid+1;i<=r;i++)
    {
        while (s<=mid && a[s]+R<a[i]) s++;
        while (e<mid && a[e+1]+L<=a[i]) e++;
        ans+=std::max(e-s+1,0);
    }
    std::sort(a+l,a+r+1);
}

int main()
{
    scanf("%d%d%d",&n,&L,&R);
    for (int i=1;i<=n;i++) scanf("%lld",a+i),a[i]+=a[i-1];
    solve(0,n);
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值