HDU 5857 Median(找中位数)

Description
给出一个长度为n的有序序列Ai,m次查询,每次查询输入两个区间[l1,r1],[l2,r2],输出将这两个区间的数放在一起后的中位数
Input
第一行一整数T表示用例组数,每组用例首先输入两整数n和m表示序列长度和查询数,之后n个整数Ai表示该序列,之后每次输入四个整数l1,r1,l2,r2表示一次查询
(T<=200,n,m<=100000,Ai最多是32位int,l1<=r1,l2<=r2)
Output
对于每次查询,输出将两个区间中数放在一起后的中位数
Sample Input
1
4 2
1 2 3 4
1 2
2 4
1 1
2 2
Sample Output
2.0
1.5 

 

如果重叠,划分成3 个区间,
l1->l2-1,l2->r1,r1+1->r2
或者
l2->l1-1,l1->r2,r2+1->r1
分别对应
a1  a2   a3  a4  a5   a6
如果是奇数
if(a2-a1+1<=x/2)
 if(a2-a1+1+(a4-a3+1)*2<=x/2)
  mid=c[a6-(x/2)]
 else
  mid=c[a4-(x/2-(a6-a5+1))/2]
else
 mid=c[a1+x/2];
如果是偶数,找x/2+1=mid2;x/2=mid1
if(a2-a1+1<=x/2-1)
 if(a2-a1+1+(a4-a3+1)*2<=x/2-1)
  mid1=c[a6-(x/2)];
 else
  mid1=c[a4-(x/2-(a6-a5+1))/2];
else
 mid1=c[a1+x/2-1];

if(a2-a1+1<=x/2)
 if(a2-a1+1+(a4-a3+1)*2<=x/2)
  mid2=c[a6-(x/2-1)];
 else
  mid2=c[a4-(x/2-1-(a6-a5+1))/2];
else
 mid2=c[a1+x/2];

不重叠
如果是奇数
if(r1-l1+1<=x/2)
 mid=c[r2-x/2];
else
 mid=c[l1+x/2];
如果是偶数mid1,mid2
if(r1-l1+1<=x/2-1)
 mid1=c[r2-x/2];
else
 mid1=c[l1+x/2-1];
if(r1-l1+1<=x/2)
 mid2=c[r2-x/2+1];
else
 mid2=c[l1+x/2;]

不能写memset,会超时,,,,,一直超时!

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100000
int c[maxn+10];
int b[maxn+10];
int d[10];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]);
        while(m--)
        {
            //memset(b,0,sizeof(b));
            int l1,r1,l2,r2;
            double mid;
            scanf("%d %d",&l1,&r1);
            scanf("%d %d",&l2,&r2);
            int x=r1-l1+r2-l2+2;
            if(r2<l1||r1<l2)
            {
                int a1,a2,a3,a4;
                if(r2<l1)
                {
                    a1=l2;a2=r2;a3=l1;a4=r1;
                    l1=a1;r1=a2;l2=a3;r2=a4;
                }
                if(x%2==1)
                {
                    if(r1-l1+1<=x/2)
                        mid=(double)c[r2-x/2];
                    else
                        mid=(double)c[l1+x/2];
                }
                else
                {
                    int mid1,mid2;
                    if(r1-l1+1<=x/2-1)
                        mid1=c[r2-x/2];
                    else
                        mid1=c[l1+x/2-1];
                    if(r1-l1+1<=x/2)
                        mid2=c[r2-x/2+1];
                    else
                        mid2=c[l1+x/2];
                    mid=((double)mid1+(double)mid2)/2;
                }

            }
            else
            {
                d[0]=l1;d[1]=r1;d[2]=l2;d[3]=r2;
                sort(d,d+4);
                l1=d[0];r1=d[2];l2=d[1];r2=d[3];
                int a1=l1,a2=l2-1,a3=l2,a4=r1,a5=r1+1,a6=r2;
                if(x%2==1)
                {

                    if(a2-a1+1<=x/2)
                        if(a2-a1+1+(a4-a3+1)*2<=x/2)
                            mid=(double)c[a6-(x/2)];
                        else
                            mid=(double)c[a4-(x/2-(a6-a5+1))/2];
                    else
                        mid=(double)c[a1+x/2];
                }
                else
                {
                    int mid1,mid2;
                    if(a2-a1+1<=x/2-1)
                        if(a2-a1+1+(a4-a3+1)*2<=x/2-1)
                            mid1=c[a6-(x/2)];
                        else
                            mid1=c[a4-(x/2-(a6-a5+1))/2];
                    else
                        mid1=c[a1+x/2-1];

                    if(a2-a1+1<=x/2)
                        if(a2-a1+1+(a4-a3+1)*2<=x/2)
                            mid2=c[a6-(x/2-1)];
                        else
                            mid2=c[a4-(x/2-1-(a6-a5+1))/2];
                    else
                        mid2=c[a1+x/2];
                    mid=((double)mid1+(double)mid2)/2;
                }

            }
            printf("%.1lf\n",mid);
        }

    }
    return 0;
}
//ff

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值