这次用的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;
}