离线处理例题

完整题目描述:

<span style="font-size:14px;">#include<stdio.h>
int a[100005][2];
int max(int a,int b){return a>b?a:b;}
int main()
{
    int n,q,i,x;
    while(scanf("%d",&n)!=EOF)//n<=100000
    {
        for(i=0;i<n;i++) scanf("%d%d",&a[i][0],&a[i][1]);//两个数均大于等于0且小于等于1000000000
        scanf("%d",&q);//q<=100000
        while(q--)
        {
            scanf("%d",&x);//0<=x<=1000000000
            int ans=-1;
            for(i=0;i<n;i++)
            {
                if(a[i][0]<x) ans=max(ans,a[i][1]);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
</span>

优化以上代码。题目大概是说:给定n个点(xi,yi)。然后q个查询,每个查询是一个a,输出x坐标小于a的最大的y,不存在则输出-1

这道题也是典型的优化>预处理优化的题目,不过这道题是离线处理

这道题的思路其实也很简单。我们只需要运用贪心的思想,一开始的时候声明一个结构体存储每个输入的x和y坐标,然后将输入的所有结构体按照y坐标值降序排序。接下来的一步便是关键步骤。由于是q次查询,我们自然想到先声明一个同样的结构体数组,将所有查询先记录下来(记录在这些结构体数组的x坐标),然后将这q次查询按照x值大小排序(这样的话能够有效的减少重复计算次数)。在这里需要注意的是我们需要将排序的q次查询进行升序排序,然后再开始遍历原来按照y值已经排序好的坐标,每次找到比待查询的x值小的坐标,便将该值对应的y坐标值存储进查询对应的y值坐标,然后内层循环终止,继续找下一个查询对应的y值。这样的话一一遍历过去,直到找到所有查询对应的y坐标值。最后再用原来临时存储的初始输入的查询值x(未排序前),进行二分查找(增加效率),将每次查询的x坐标值对应的y坐标值一一输出即可。

完整的优化源代码如下:

#include<cstdio>
#include<algorithm>
using namespace std;
struct coord
{
    int x;
    int y;
} a[100005];
coord que[100005];           //用来存储询问的x坐标,再离线处理y坐标
void quick_sort(int left,int right,coord b[],bool flag);
int main()
{
    int n,q;
    while(scanf("%d",&n)!=EOF)//n<=100000
    {
        for(int i = 0; i<n; i++)    scanf("%d%d",&a[i].x,&a[i].y); //两个数均大于等于0且小于等于1000000000
        quick_sort(0,n-1,a,true);
        scanf("%d",&q);//q<=100000
        coord temp_q[100005];
        for(int i = 0;i < q;i++)
        {
            scanf("%d",&que[i].x);       //输入查询的x值
            que[i].y = -1;
        }
        for(int i = 0;i < q;i++)
            temp_q[i] = que[i];             //存储查询的初始值
        quick_sort(0,q-1,que,false);              //将查询的x值按照升序排序
        int flag = 0;
        for(int j = 0;j < q;j++)
        {
            for(int i = flag;i < n; i++)
            {
                if(a[i].x < que[j].x)
                {
                    flag = i;                   //更新当前扫描到的值
                    que[j].y = a[i].y;
                    break;
                }
            }
        }
        for(int i = 0;i < q;i++)
        {
            int mid,low = 0,high = q;
            while(low <= high)   //二分查找并输出,升序数组中查找
            {
                mid = (low + high) / 2;
                if(que[mid].x > temp_q[i].x)        low = mid + 1;
                else if(que[mid].x < temp_q[i].x)   high = mid - 1;
                else if(que[mid].x == temp_q[i].x)
                {
                    printf("%d\n",que[mid].y);
                    break;
                }
            }
        }

    }
    return 0;
}
void quick_sort(int left,int right,coord b[],bool flag)
{
    int temp,i,j;               //用来存储基准数
    coord temp_coord = b[left];       //每次都以最左边的数字作为基准数
    if(left >= right)   return;
    i = left;
    j = right;
    while(i < j)
    {
        while((i < j && b[j].y <= b[left].y && flag) || (i < j && b[j].x <= b[left].x && !flag))
            j--;
        while((i < j && b[i].y >= b[left].y && flag)  || (i < j && b[i].x >= b[left].x && !flag))
            i++;
        if(i < j)
        {
            coord flag = b[j];
            b[j] = b[i];
            b[i] = flag;
        }
    }
    b[left] = b[i];
    b[i] = temp_coord;       //基准数归位
    quick_sort(left,i - 1,b,flag);
    quick_sort(i + 1,right,b,flag);   //排序基准数左边和右边的序列
}


如有错误,还请指正,O(∩_∩)O谢谢

http://www.niftyadmin.cn/n/1038251.html

相关文章

js原生基础DOM操作

常用的dom操作如下 document.getElementById("id"); //通过ID名获取元素 document.getElementsByTagName("div"); //通过标签名获取元素 document.getElementsByClassName("class"); //通过类名获取元素 document.querySelector("se…

JavaScript生成范围随机数的方法

也许我们经常会遇到需要一个在一定范围内生成的随机数 例如 0 到 10之间参数以位随即谁&#xff0c;可js自带的功能里却无法实现这个需求 那么我们只好手动封装一个了 function random(n,m) {var comt m - n 1;return Math.floor(Math.random() * comt n) }然后我们调用方法…

C语言中 ln(以自然对数e为底) lg(以十为底) 以及logab(以a为底,b为真数)的相关知识

总所周知&#xff0c;我们在高中学过对数函数&#xff0c;记作ylogax。下面是百度百科关于对数函数的描述&#xff1a; 对数的定义&#xff1a;一般地&#xff0c;如果axN&#xff08;a>0&#xff0c;且a≠1&#xff09;&#xff0c;那么数x叫做以a为底N的对数&#xff0c;记…

React基础整理

前端一直流传着三大框架一大抄的说法&#xff0c;在中国的你或许无时不在感受这vue的强大&#xff0c;但其实react才是三大框架中世界使用了最大的 react官方地址 : http://react.html.cn/docs/getting-started.html 在这里我必须说明&#xff0c;react和vue谁更好是个争论不休…

浮点数比较大小的问题

浮点数比较大小&#xff0c;由于精度问题&#xff0c;所以直接比较有时可能会出错。 单精度数7位有效数字。 &#xff08;float&#xff09; 双精度数16位有效数字。&#xff08;double&#xff09; 单精度数的尾数用23位存储&#xff0c;加上默认的小数点前的1位1&#xff0c;…

JavaScript 节流 防抖

首先我们要明白什么是节流 什么又是放抖 其实也很简单&#xff0c;都是防止同一个事件在短时间内重复触发多次。 但区别在于防抖是单纯的为提高用户体验&#xff0c;比如一个按键用户不停的点击&#xff0c;就会不停的发请求&#xff0c;而这时防抖就要让用户的频繁点击只发一次…

Codeforces Round #341 (Div. 2)总结

A题&#xff1a; A题题目链接 题目描述&#xff1a; A. Wet Shark and Odd and Eventime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputToday, Wet Shark is given n integers. Using any of these integers no more…

STL list链表的用法详解

本文以List容器为例子&#xff0c;介绍了STL的基本内容&#xff0c;从容器到迭代器&#xff0c;再到普通函数&#xff0c;而且例子丰富&#xff0c;通俗易懂。不失为STL的入门文章&#xff0c;新手不容错过! 0 前言 1 定义一个list 2 使用list的成员函数push_back和push_front插…