二分查找+lowbit

题目背景

在 30XX 年,由于科学家和工程师的不断努力,不同星球之间的互动变得非常活跃。比太郎是一只河狸,他现在是一项交流项目的大使。他的任务是向不同星球的居民介绍地球上的食物。他将在下午 1 点出发去 JOI 星球。

现在,比太郎正计划向 JOI 星球的居民介绍 castella。castella 已经被切成了若干段。castella 是一种由面粉、鸡蛋、糖和淀粉糖浆制成的烘烤海绵蛋糕。

题目描述

castella 的形状是一个在水平方向上很长的长方体。它被切成了 NN 段,其中从左往右的第 ii 段的长度为整数 A_iAi​。

几分钟前,我们得知 JOI 星球的居民不喜欢偶数。为了解决此问题,你需要不断执行下列操作,直到不存在长度为偶数的段。

  1. 在长度为偶数的段中,你选择最靠右的一段。
  2. 你将选中的这一段切成两个长度相等的段。也就是说,假设选中的这一段的长度是 kk,你将其切成长度为 \displaystyle \frac{k}{2}2k​ 的两段。你不改变其他段的位置。

为了确认操作是否被正确地执行了,比太郎让你回答 QQ 个询问。第 jj 个询问如下:

  • 当所有操作执行完毕后,从左往右的第 X_jXj​ 段的长度为多少?

给定 castella 的信息与询问,请写一个程序回答所有询问。

输入格式

第一行,一个正整数 NN。

接下来 NN 行,第 ii 行一个正整数 A_iAi​。

接下来一行,一个正整数 QQ。

接下来 QQ 行,第 jj 行一个正整数 X_jXj​。

输出格式

输出 QQ 行,第 jj 行一个数,表示第 jj 个询问的答案。

输入输出样例

输入 #1复制

4
14
9
8
12
6
2
3
5
7
11
13

输出 #1复制

7
9
1
1
1
3

输入 #2复制

13
1
4
1
4
2
1
3
5
6
2
3
7
3
8
2
10
11
13
15
17
18
20

输出 #2复制

1
1
1
1
5
3
1
3

输入 #3复制

16
536870912
402653184
536870912
536870912
134217728
536870912
671088640
536870912
536870912
536870912
939524096
805306368
536870912
956301312
536870912
536870912
5
2500000000
3355443201
4294967296
5111111111
6190792704

输出 #3复制

5
1
7
57
1

说明/提示

【样例解释 #1】

一开始,castella 从左到右的段的长度分别为 14, 9, 8, 1214,9,8,12。

当所有操作执行完毕后,castella 被切成了 1515 段。从左到右的段的长度分别为 7, 7, 9, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 37,7,9,1,1,1,1,1,1,1,1,3,3,3,3。

这个样例满足子任务 2, 32,3 的限制。

【样例解释 #2】

这个样例满足所有子任务的限制。

【样例解释 #3】

这个样例满足子任务 2, 32,3 的限制。


【数据范围】

本题采用捆绑测试。

对于 100 \%100% 的数据,1 \le N, Q \le 2 \times {10}^51≤N,Q≤2×105,1 \le A_i \le {10}^91≤Ai​≤109,1 \le X_j \le {10}^{15}1≤Xj​≤1015,X_j \le X_{j + 1}Xj​≤Xj+1​,保证当所有操作执行完毕后,castella 被切成了至少 X_QXQ​ 段。

  • 子任务 11(2525 分):A_i \le 8Ai​≤8。
  • 子任务 22(3535 分):N, Q \le 1000N,Q≤1000。
  • 子任务 33(4040 分):无特殊限制。

译自 JOI 2022 Final T1「インターカステラー / Intercastellar

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
typedef long long ll;
ll a[maxn],sum[maxn];
int n,q;
ll lowbit(ll y)
{
    return y&-y;
}
ll lowbou(ll a[],ll l,ll r,ll tar)
{
	while(l<=r){
		ll mid=(l+r)/2;
		if (a[mid]<tar) l=mid+1;
		else r=mid-1;
	}
	return l;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=sum[i-1]+lowbit(a[i]);
    }
    cin>>q;
    while(q--)
    {
        ll x;
        cin>>x;
        ll xx=lowbou(sum,1,n,x);
        cout<<a[xx]/lowbit(a[xx])<<endl;
    }

    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值