北航OJ刷题

文章目录

  • 题目1:D&C--玲珑数题面
    • 输入
    • 输出
    • 输入样例
    • 输出样例
    • 解题思路
    • 代码
    • 结语

题目1:D&C–玲珑数题面

Bamboo听说知道了正确的玲珑数,就能开启玲珑阵,穿越时空,然后解锁一个满分玛丽苏cp……

于是决定停止幻想,现在就去算玲珑数。

玲珑数是什么呢?

在数列中任意两个数a[i],a[j],如果i2*a[j],那么a[i]和a[j]就构成了一对儿玲珑对。玲珑数就是玲珑对的总数。

是不是听起来很简单?快帮Bamboo算一下玲珑数是多少吧!

输入

多组输入数据

输入的第一个数是正整数n,表示数组长度,0

接下来n个正整数是数组an,均在int范围内。

然后是正整数t表示t次查询 ,0< t<1000

接下来t行,每行两个数p和q,代表查询的数组下标区间 0<=p

输出

每次查询输出一行,为所求区间内的玲珑数。

输入样例

3
3 2 1
1
0 2

输出样例

1

解题思路

第一反应就是这道题很像“序列优美差值”那道题,应该可以用分治法解决。把数组分成两A,B两部分,那么A部分里的数,下标一定小于B内的数,满足条件i

代码

/*注意由于涉及到多次查询,不能直接操作a数组,这会改变某一区间内的元素排列顺序,所以要将查询
的区间提取出来,这卡了我好一会*/
#include
#include
#include
#include
using namespace std;

void msort(int l, int r);
void merge(int l,int r);

long long ans=0;
long long a[10004];
long long b[10004];
long long A[10004];
int n,t,p,q;
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        scanf("%d",&t);
        for(int i=1;i<=t;i++)
        {
            ans=0;
            scanf("%d%d",&p,&q);
            if(p>q)//注意p,q的值,数据不保证p
            {
                int temp=p;
                p=q;
                q=temp;
            }
            int k=1;
            for(int j=p;j<=q;j++)
            {
                A[k++]=a[j+1];//由于输入时我将数组首元素放在了a[1]的位置,所以这里取j+1才对,也卡了一会
            }
            msort(1,q-p+1);
            printf("%lld\n",ans);
        }
    }
}


void msort(int l,int r)
{
    if(l>=r)
        return;
    int mid=(l+r)/2;
    msort(l,mid);
    msort(mid+1,r);
    merge(l,r);
}

void merge(int l,int r)
{
    int mid=(l+r)/2;
    int st=mid+1;
    for(int i=l;i<=mid;i++)//这里的l最初我写成1了,忧桑,应该是从左界开始才对嘛,我的分治学的还不够好
    {
        while(A[i]>(2*A[st])&&st<=r)
        {
            st++;
        }
        ans+=(st-1-mid);
    }

//下面是,正常的归并排序
    int x = l, y = mid + 1, i = l;
	while(x <= mid && y <= r) {
		b[i++] = A[x] <= A[y] ? A[x++] : A[y++];
	}
	for(int k = y; k <= r; ++k) b[i++] = A[k];
	for(int k = x; k <= mid; ++k) b[i++] = A[k];
	for(int i = l; i <= r; ++i) A[i] = b[i];

}

结语

以后我会争取每天都至少更新一道题,主要是为了以输出的形式,获得知识和技能的输入。第一次写博客,写的不好的地方,还请多多见谅。

你可能感兴趣的:(北航OJ刷题)