NOIP机房模拟 【计算几何】【花花的聚会】【文本编辑器】

七月最后一个星期的集训,周一一来就模拟考试。。

计算几何

题意描述

花花对计算几何有着浓厚的兴趣。他经常对着平面直角坐标系发呆,思考一些有趣的问题。今天,他想到了一个十分有意思的题目:
首先,花花会在x 轴正半轴和y 轴正半轴分别挑选n 个点。随后,他将x 轴的点与y 轴的点一一连接,形成n 条线段,并保证任意两条线段不相交。花花确定这种连接方式有且仅有一种。最后,花花会给出m 个询问。对于每个询问,将会给定一个点P(xp; yp),问线段
OP(O 为坐标原点)与n 条线段会产生多少个交点?

输入格式

第1 行包含一个正整数n,表示线段的数量;
第2 行包含n 个正整数,表示花花在x 轴选取的点的横坐标;
第3 行包含n 个正整数,表示花花在y 轴选取的点的纵坐标;
第4 行包含一个正整数m,表示询问数量;
随后m 行,每行包含两个正整数xp 和yp,表示询问中给定的点的横、纵坐标。

输出格式

共m 行,每行包含一个非负整数,表示你对这条询问给出的答案。

样例输入

3
4 5 3
3 5 4
2
1 1
3 3

样例输出

0
3

思路:

考虑二分。
对于每一个询问,OP只和在P左下角的线段相交。故我们可以二分
在P左下角的最靠上的线段,从而得到答案。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e5;
int n,m;
long long one,two;
long long x[N+5],y[N+5];
int main()
{
    freopen("geometry.in","r",stdin);
    freopen("geometry.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    scanf("%d",&x[i]);
    for (int i=1;i<=n;i++)
    scanf("%d",&y[i]);
    sort(x+1,x+1+n);sort(y+1,y+1+n);
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&one,&two);
        int lf=1,rt=n;
        while(lf<=rt)
        {
            int mid=(lf+rt)>>1;
            if (x[mid]*two+y[mid]*one>=x[mid]*y[mid]) lf=mid+1;
            else rt=mid-1;
        }
        printf("%d\n",rt);
    }
    return 0;
}

花花的聚会

题意描述

花花住在H 国。H 国有n 个城市,其中1 号城市为其首都。城市间有n - 1 条单向道路。从任意一个城市出发,都可以沿着这些单向道路一路走到首都。事实上,从任何一个城市走到首都的路径是唯一的。
过路并不是免费的。想要通过某一条道路,你必须使用一次过路券。H 国一共有m 种过路券,每张过路券以三个整数表示:v k w:你可以在城市v 以价格w 买到一张过路券。这张券可以使用k 次。这意味着,拿着这张券通过了 条道路之后,这张券就不能再使用了。
请注意你同一时间最多只能拥有最多一张过路券。但你可以随时撕掉手中已有的过路券,并且在所在的城市再买一张。
花花家在首都。他有q 位朋友,他希望把这些朋友们都邀请到他家做客。所以他想要知道每位朋友要花多少路费。他的朋友们都很聪明,永远都会选择一条花费最少的方式到达首都。
花花需要准备晚餐去了,所以他没有时间亲自计算出朋友们将要花费的路费。你可以帮帮他么?

输入格式

输入的第一行包含两个空格隔开的整数n 和m,表示H 国的城市数量和过路券的种数。
之后的n - 1 行各自包含两个数ai 和bi,代表城市ai 到城市bi 间有一条单向道路。
之后的m 行每行包括三个整数vi; ki 和wi,表示一种过路券。
下一行包含一个整数q,表示花花朋友的数量。
之后的q 行各自包含一个整数,表示花花朋友的所在城市。

输出格式

输出共q 行,每一行代表一位朋友的路费。

样例输入

7 7
3 1
2 1
7 6
6 3
5 3
4 3
7 2 3
7 1 1
2 3 5
3 6 2
4 2 4
5 3 10
6 1 20
3
5
6
7

样例输出

10
22
5

思路

不难发现,我们可以用动态规划的思想来解决这个问题。记f[u] 为u 跳到根的最少代价。则不难得出转移方程:f[u] = minff[v]+wig,其中v 是u 的祖先,且存在一种车票ui;wi; ki,并满足dep[u] -dep[v]<= ki。这个DP方程的边界条件为f[root] = 0。这样对于每种车票,我们可以暴力枚举所有合法的v,从而求得答案。
但是,考虑优化解法三的DP转移。事实上我们只需在较快的时间内求得树上某一段区间的min,即可较好地解决这个问题。而维护树上区间最值有树链剖分、动态树等许多数据结构能够胜任。在这里我们考虑用倍增的思想,维护u 往上跳2i 步到的祖先v 和u 到v 这一段f 值的最小值,这样我们对于每一个节点u 可以在O(logn) 的时间内求得minff[v]g。
时间复杂度为O(nlogn),期望得分100 分。

代码

然而我用记忆化搜索照样过,速度飞快。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namesp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值