11.2队内胡策

4 篇文章 0 订阅
1 篇文章 0 订阅

这次用的zhx的题目,zhx的题目还是一如既往的劲啊233。
t1数据有问题,看题面是可以拿栈搞一搞就过,但数据与题面不符,导致栈在不特判的情况下只能拿到30分,这里对t1就不多描述。


t2

【问题描述】

栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序。例如,借
助一个栈,依次将数组 1,3,2 按顺序入栈或出栈,可对其从大到小排序:
1 入栈;3 入栈;3 出栈;2 入栈;2 出栈;1 出栈。
在上面这个例子中,出栈序列是 3,2,1,因此实现了对数组的排序。
遗憾的是,有些时候,仅仅借助一个栈,不能实现对数组的完全排序。例如
给定数组 2,1,3,借助一个栈,能获得的字典序最大的出栈序列是 3,1,2:
2 入栈;1 入栈;3 入栈;3 出栈;1 出栈;2 出栈。
请你借助一个栈,对一个给定的数组按照出栈顺序进行从大到小排序。当无
法完全排序时,请输出字典序最大的出栈序列。

【输入格式】

输入共2行。
第一行包含一个整数n,表示入栈序列长度。
第二行包含n个整数,表示入栈序列。输入数据保证给定的序列是1到 n 的全
排列,即不会出现重复数字。

【输出格式】

仅一行,共n个整数,表示你计算出的出栈序列。

【样例输入】

3
2 1 3

【样例输出】

3 1 2

【样例解释】

这回山里有座塔。

【数据规模与约定】

对于30%的数据,1 ≤n≤ 10^3。
对于60%的数据,1 ≤n≤ 10^5。
对于100%的数据,1 ≤n≤ 10^6。
一个比较简单的贪心,大体意思是用栈来保证一个数列的字典序最大,算法关键是在记录当前的最大值是否在栈里,在的话令最大值–,不在的话就把元素一直入栈直到当前的最大值入栈,具体见代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int sz = 2000100;
stack < int > s;
int num[sz];
bool use[sz];
int n;
int read()
{
    int x = 0 , f = 1;
    char in = getchar();
    while(in < '0' || in > '9')
    {
        if(in == '-')
            f = -1;
        in = getchar();
    }
    while('0' <= in && in <= '9')
    {
        x = (x << 3) + (x << 1) + in - '0';
        in = getchar();
    }
    return x * f;
}
void start_work()
{
    n = read();
    for(int i = 1 ; i <= n ; i ++)
        num[i] = read();
}
int main()
{
    freopen("haha.in","r",stdin);
    freopen("haha.out","w",stdout);
    start_work();
    int now = n;
    for(int i = 1 ; i <= n ; i ++)
    {
        if(num[i] == now)
        {
            printf("%d ",num[i]);
            now --;
            while(use[now])
                now --;
            while(!s.empty() && now < s.top())
            {
                use[s.top()] = 0;
                printf("%d ",s.top());
                s.pop();
            }
        }
        else
            s.push(num[i]) , use[num[i]] = 1;
    }
    while(!s.empty())
    {
        printf("%d ",s.top());
        s.pop();
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
/*
10
3 10 1 6 4 5 9 7 8 2

10 9 8 7 5 4 6 2 1 3
*/

t3

【问题描述】

小 Q 对计算几何有着浓厚的兴趣。他经常对着平面直角坐标系发呆,思考
一些有趣的问题。今天,他想到了一个十分有意思的题目:
首先,小 Q 会在x轴正半轴和y轴正半轴分别挑选n个点。随后,他将x轴的
点与y轴的点一一连接,形成n条线段,并保证任意两条线段不相交。小 Q 确定这种连接方式有且仅有一种。最后,小 Q 会给出m个询问。对于每个询问,将会给定一个点P(Px, Py),请回答线段 OP 与n条线段会产生多少个交点?
小 Q 找到了正在钻研数据结构的你,希望你可以帮他解决这道难题。
【输入格式】
第1行包含一个正整数n,表示线段的数量;
第2行包含n个正整数,表示小 Q 在x轴选取的点的横坐标;
第3行包含n个正整数,表示小 Q 在y轴选取的点的纵坐标;
第 4 行包含一个正整数m,表示询问数量;
随后m行,每行包含两个正整数Px,Py,表示询问中给定的点的横、纵坐标。
【输出格式】
共m行,每行包含一个非负整数,表示你对这条询问给出的答案。
【样例输入】
3
4 5 3
3 5 4
2
1 1
3 3
【样例输出】
0
3
【样例解释】
然后塔里啥都没有。
【数据规模与约定】
对于50%的数据,1≤n,m,≤2x10^3。
对于100%的数据,1≤n,m≤2×10^5
,坐标范围≤ 10^8。
自学oi以来第一次在手动读入上翻车233,题目答案单调性显然,二分后验证就是小学数学了,这题数据挺良心的也不会卡精度。
代码如下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define eps 1e-9
using namespace std;
const int sz = 400010;
int n,m;
int x_pos[sz];
int y_pos[sz];
double k[sz];
double b[sz];
int read()
{
    int x = 0 , f = 1;
    char in = getchar();
    while(in < '0' || in > '9')
    {
        if(in == '-')
            f = -1;
        in = getchar();
    }
    while('0' <= in && in <= '9')
    {
        x = (x << 3) + (x << 1) + in - '0';
        in = getchar();
    }
    return x * f;
}
double calc_k(double x1,double y1,double x2,double y2)
{
    return (y1 - y2) / (x1 - x2);
}
double calc_b(double x1,double y1,double x2,double y2)
{
    double kk = (y1 - y2) / (x1 - x2);
    return y1 - x1 * kk;
}
double calc_x(double k1,double b,double k2)
{
    return b / (k2 - k1);
}
void start_work()
{
    n = read();
    for(int i = 1 ; i <= n ; i ++)
        x_pos[i] = read();
    for(int i = 1 ; i <= n ; i ++)
        y_pos[i] = read();
    sort(x_pos+1,x_pos+n+1);
    sort(y_pos+1,y_pos+n+1);
    for(int i = 1 ; i <= n ; i ++)
        k[i] = calc_k((double)x_pos[i],0.0,0.0,(double)y_pos[i]),
        b[i] = calc_b((double)x_pos[i],0.0,0.0,(double)y_pos[i]);
}
bool check(int mid,double k2,double pos_x,double pos_y)
{
    if(calc_x(k[mid],b[mid],k2) <= pos_x)
        return true;
    return false;
}
int EF(int pos_x,int pos_y)
{
    double k2 = ((double)pos_y) / ((double)pos_x);
    int l = 0 , r = n;
    while(r - l > 1)
    {
        int mid = l + r >> 1;
        if(check(mid,k2,(double)pos_x,(double)pos_y))
            l = mid;
        else
            r = mid;
    }
    if(check(r,k2,(double)pos_x,(double)pos_y))
        return r;
    return l;
}
int main()
{
    freopen("hahaha.in","r",stdin);
    freopen("hahaha.out","w",stdout);
    start_work();
    m = read();
    for(int i = 1 ; i <= m ; i ++)
    {
        int x = read() , y =read();
        printf("%d\n",EF(x,y));
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值