HDU 6040 Hints of sd0061 思维

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

  题目大意: 给定数组a, b。要求输出和B长度相同的数组C, C[i]为在A中排名为B[i]的数, 重新排A数组, 使得a[i]必须是a数组中第b[i]+1大的数

  解题思路: 首先我们要把数组A求出来。第一想法就是最单纯的将A排个序, 然后输出A[B[i]], 自己还恬不知耻的去交了一发, 要是这都不会T, 还叫啥ACM啊......

        好吧, 我题意理解错了......自己太浮躁了, 检讨一下自己。 有时候数据会给的非常极端来误导你.......记住了 .... 以后不要这样了。先将B数组排序, 这里用到了一个快排的思想, 库函数为nth_element(a, a+k, a+n), 将第K大的元素放在数组的下标K上, 左面全比他小, 右面全比他大, 也就是说如果k是由大到小的话可以省去一半左右的时间, 这题也是卡这个的, 还有一个问题就是可能会出现n < m 的情况, 这时候为了加快速度可以通过b[pos[i]] == b[pos[i+1]]来提前判定。

  代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>

using namespace std;
typedef long long ll;

unsigned int a[10000010];
unsigned int x,y,z;
unsigned int rng61()
{
    unsigned int t;
    x ^= x << 16;
    x ^= x >> 5;
    x ^= x << 1;
    t = x;
    x = y;
    y = z;
    z = t ^ x ^ y;
    return z;
}
int b[105];
int n,m,pos[105];
unsigned int ans[105];
bool cmp(int x,int y)
{
    return b[x]<b[y];
}
int main()
{
    int v=1;
    while(scanf("%d%d%u%u%u",&n,&m,&x,&y,&z)!=EOF)
    {
        for(int i=0;i<m;i++)
        {
            scanf("%d",&b[i]);
            pos[i]=i;
        }
        sort(pos,pos+m,cmp);//通过b的大小对下标排序。
        for(int i=0;i<n;i++)
        {
            a[i]=rng61();
        }
        b[pos[m]=m]=n;
        for(int i=m-1;i>=0;i--)
        {
            if(b[pos[i]]==b[pos[i+1]])
            {
                ans[pos[i]]=ans[pos[i+1]];
                continue;
            }
            nth_element(a,a+b[pos[i]],a+b[pos[i+1]]);
            ans[pos[i]]=a[b[pos[i]]];
        }
        printf("Case #%d:",v++);
        for(int i=0;i<m;i++)
        {
            printf(" %u",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

  思考: 我学到了一个小小的skill, 如果对一个数组进行排序如果还想保留下标的信息的话, 不妨再创建一个下标数组, 然后写好cmp函数, 这时候排序的仅仅是下标, 不仅达到了目的, 还保留了原数组,  很巧妙, 这是一道很费脑筋的题, 只有多练才能在正式的比赛上想到这种方法吧

时间: 2024-11-13 11:09:12

HDU 6040 Hints of sd0061 思维的相关文章

HDU 6040 Hints of sd0061 —— 2017 Multi-University Training 1

Hints of sd0061 Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2297    Accepted Submission(s): 687 Problem Description sd0061, the legend of Beihang University ACM-ICPC Team, retired last yea

HDU 6040 Hints of sd0061 nth_element函数

Hints of sd0061 Problem Description sd0061, the legend of Beihang University ACM-ICPC Team, retired last year leaving a group of noobs. Noobs have no idea how to deal with m coming contests. sd0061 has left a set of hints for them. There are n noobs

HDU 6040 Hints of sd0061(nth_element)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6040 [题目大意] 给出一个随机数生成器,有m个询问,问第bi小的元素是啥 询问中对于bi<bk,bj<bk,有bi+bj<=bk [题解] 我们将所有的询问排序,我们发现倒着处理询问的时候询问区间大小下降非常快, nth_element(start,start+k,end) 可以近似O(n)查询区间中第k小的数字, 并且在处理后保证比第k小小的数字均在其前面(虽然不一定有序), 所以我

hdu 6040 -Hints of sd0061(STL)

Problem Description sd0061, the legend of Beihang University ACM-ICPC Team, retired last year leaving a group of noobs. Noobs have no idea how to deal with m coming contests. sd0061 has left a set of hints for them. There are n noobs in the team, the

HDU 6040 stl

Hints of sd0061 Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2421    Accepted Submission(s): 736 Problem Description sd0061, the legend of Beihang University ACM-ICPC Team, retired last yea

HDU 6154 CaoHaha&#39;s staff 思维 找规律

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6154 题目描述: 围成一个面积不小于S的多边形, 最少需要多少根儿线段, 线段可以为单元格边或者对角线 解题思路: 最大的面积肯定是由根号2为边长的正方形围成了, 那么我们把所有正方形都遍历一遍, 找出S介于N, N+1的那个上界N+1设为max, 因为MAX所围成的多边形面积和MAX-1, MAX-2, MAX-3围成的多边形面积, 找出满足条件的最小的一个即可 代码: #include <io

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha&#39;s staff 思维

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6154 题意:在笛卡尔坐标系下,画一个面积至少为  n 的简单多边形,每次只能画一条边或者一个格子的对角线,问至少要画几条. 解法:如果一个斜着的矩形长宽分别是 a,b,那么它的面积是 2ab.最优解肯定是离 sqrt(n/2)很近的位置.想想 n=5 时答案为什么是7 然后在那个小范围内枚举一下就好了.我给一张做题时画的图 #include <bits/stdc++.h> using namesp

hdu 4710 Balls Rearrangement (数学思维)

题意:就是  把编号从0-n的小球对应放进i%a编号的盒子里,然后又买了新盒子, 现在总共有b个盒子,Bob想把球装进i%b编号的盒子里.求重置的最小花费. 每次移动的花费为y - x ,即移动前后盒子编号的差值的绝对值. 算法: 题目就是要求                  先判断  n与  lcm(a,b)的大小,每一个周期存在循环,这样把区间缩短避免重复计算. 如果n>lcm(a,b)则   ans = (n/lcm)*solve(lcm)+solve(n%lcm) 否则   ans =

HDU 3972 1 M possible(思维)

1 M possible Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 2048/1024 K (Java/Others) Total Submission(s): 1031    Accepted Submission(s): 343 Problem Description There are 3*N+2 nonnegative integers. Except two special integers, the rest 3