HDU 5857 Median (2016 多校训#10 1001)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5857

题意:给出一个已排好的序列,再给出两个范围(l1,r1,l2,r2),求由着两个子序列 组成的新序列的中位数,结果保留一位小数。

官方题解:

一个数组上的两个区间求中位数,可以通过分类讨论直接找到中位数,复杂度O(1).不过本题数据较小,优美的log(n)也可过.

分析:我用的是前者的方法。弄一个函数求新序列排第X在原序列的下标,如果长度是奇数,直接求排在第len/2+1位上的,偶数则中间两个的平均数。

找之前我先处理了一下,让l1<=l2。

中位数:将序列排好序后取中间的数,偶数序列则为中间二数和除2;

函数中主要讨论三种情况,一种是l2>=r1(1 2 3 4),这种最简单,直接找,第二种是有重叠部分(类似1 3 2 5),第三种(类似1 5 2 3)是第二串是第一串的子串,这种我发现和第二种是一样的,于是直接转化成第二种。(例如 1 5 2 3和1 3 2 5结果肯定是一样的);

(ps:由于复制后修改了第二种忘记改第三种了,于是WA了两次。)

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<cstdlib>
#include<iomanip>
#include<string>
#include<vector>
#include<map>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
#define Max(a,b) (a>b)?a:b
#define lowbit(x) x&(-x)
int l1,l2,r1,r2,sum;
double a[100005];
double ans(int x)
{
    if(r1<=l2)
    {
        if(x<=r1-l1+1)
        {
            return a[l1+x-1];
        }
        else
        {
            return a[l2+x-1-r1+l1-1];
        }
    }
    else if(r1<=r2)
    {
        if(x<=l2-l1)
        {
            return a[l1+x-1];
        }
        else if(x>r1-l1+1+r1-l2+1)
        {
            return a[l2+x-r1+l1-1-1];
        }
        else
        {
            return a[l2+(x-l2+l1+1)/2-1];
        }
    }
    else
    {
        swap(r1,r2);
        if(x<=l2-l1)
        {
            return a[l1+x-1];
        }
        else if(x>r1-l1+1+r1-l2+1)
        {
            return a[l2+x-r1+l1-1-1];
        }
        else
        {
            return a[l2+(x-l2+l1+1)/2-1];
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%lf",&a[i]);
        }
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
            if(l1>l2)
            {
                swap(l1,l2);
                swap(r1,r2);
            }
            sum=r1-l1+1+r2-l2+1;
            if(sum%2)
            {
                printf("%.1f\n",ans(sum/2+1));
            }
            else
            {
                printf("%.1f\n",(ans(sum/2)+ans(sum/2+1))/2);
            }
        }
    }
}
View Code

 

posted @ 2016-08-18 21:42  wwdf  阅读(225)  评论(0编辑  收藏  举报