码迷,mamicode.com
首页 > 其他好文 > 详细

3.25考试(hnoi难度)----神奇的一日游

时间:2016-03-26 20:24:44      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:

T1怕老婆

  有一天hzy9819,来到了一座大城市拥有了属于他自己的一双滑板鞋。但是他还是不满足想要拥有属于自己的一栋楼,他来到了一条宽敞的大道上,一个一个记录着这些楼的层数以方便自己选择。

  hzy9819因为欣欣的要求,所以只喜欢高度h mod p=k的房子。但hzy9819是个鬼畜boy,他总是忘记欣欣的要求,但他不知道其实不是他记错了而是每次欣欣讲的p k都不同。

     假设hzy9819每次知道了欣欣要求后是从大道的li点进入,ri点出去。因为害怕老婆的hzy9819怕自己数错,所以请你帮忙统计每次满足鬼女要求的楼有多少栋。

  

【数据说明】

            30%:n<=1000,m<=2000

            100%: 0<n,m<=10^5,任意1<=i<=n满足hi<=10^4,0<p<=10^4,0<=k<p。

 

【样例输入】

    5 2

       1 5 2 3 7

       1 3 2 1

       2 5 3 0

【样例输出】

       2

       1

  这题只有7,8个人想出来了。(还有两个是我教的----啦啦啦!)

  当我看到h<=10000的时候我就看穿了一切。我们用一个数组(先假设是一个数组式的数据结构)a[i][j]:i表示高度为i的房子,j表示第j个高度为i的房子在什么位置。数组a[i]会是递增的。那么我们用一个整数x,用x*p+k来枚举h,再去枚举数组当中每一个h的位置是否满足l,r的要求。然后就可以获得80分,丑一点70分。

  然后,我们可以用邻接表来优化,二分查找优化常数,当P<=10的时候直接枚举,就可以AC了。(别忘了读入优化)

80分代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#define RE register
using namespace std;
int j,k,x,n,m,l,r,p,ans,maxh,next[300000],head[300000],w[300000];
vector <int> a[11000];
int getint()
{
int w=0,q=0;
char c=getchar();
while((c<‘0‘||c>‘9‘)&&c!=‘-‘) c=getchar();
if(c==‘-‘) q=1,c=getchar();
while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar();
return q?-w:w;
}
int main()
{
freopen("henpecked.in","r",stdin); freopen("henpecked.out","w",stdout);
n=getint(),m=getint();
for (RE int i=1;i<=n;i++)
{
x=getint();
next[i]=head[x]; head[x]=i; w[i]=i;
maxh=max(maxh,x);
//a[x].push_back(i);
}
for (RE int q=1;q<=m;q++)
{
l=getint(),r=getint(),p=getint(),k=getint();
if (p==1) {cout<<r-l+1<<endl; continue;}
x=k-p; ans=0;
while (x+p<=maxh)
{
x+=p;
//j=a[x].size();
for (RE int i=head[x];i!=0;i=next[i])
if (w[i]>=l && w[i]<=r) ans++;
}
printf("%d\n",ans);
}
return 0;
}

T2  保护家园

 

  在一次偶然的情况下,科学家知道金字塔是古人类为了保护自己抵御外星人入侵而建立的保护塔,它的保护范围为一个R半径的圆形。

  因为古人类要保留尽可能多的资源来对外星人进行反扑,所以他们希望保护的范围尽量的小。又因为要为人类保留香火所以要至少保护住k个居住点,这样才能让所有人类住下。现在国王不知道最小确定的R是多少,所以他穿越了千年来找你,要你帮他计算一下。如果你找不到,他就把你“嘿嘿嘿”。

【输入格式】

           程序的第一行输入数据为两个整数:N和K(2≤K≤N≤500)——N为居住点的数目,K为至少保护k个居住点。

     接下来的N行中,每一行包括了一对整数:X和Y(0≤X, Y≤10,000)——(X,Y)是居住点的坐标。“居住点”的坐标不会重复。保证有合法解。

【输出格式】

仅一行,包含一个实数。推荐保留8位小数。

【样例】

Sample Input 1 (Sputtering.in)

Sample Output 1 (Sputtering.out)

10 5

1 8

2 6

4 8

2 2

9 7

8 5

5 3

3 3

4 6

4 1

2.23606797

 

Sample Input 2

Sample Output 2

4 3

2 2

6 2

6 5

2 8

2.50000000

 

【数据说明】

  35%的数据保证N<=100

  100%的数据保证N<=500

  我们知道此题圆有一个性质,至少会有两个或两个以上的点在圆上。那么知道了这个结论之后能有什么用呢?           答案是:没什么卵用。

  我不会写这道题的正解。

  贪心,枚举两两点对,然后看有多少个点在以枚举出的点对为直径的圆中。O(n^3);

45分代码:

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cstring>

#include<cmath>

using namespace std;

int i,j,k,x,n,m,tot;

double a[510][3],ans;

double maxn;

int main()

{

freopen("fagttering.in","r",stdin); freopen("fagttering.out","w",stdout);

cin>>n>>m;

ans=0x7fffffff;

for (i=1;i<=n;i++) cin>>a[i][1]>>a[i][2];

for (i=1;i<n;i++)

for (j=i+1;j<=n;j++)

{

double xx=(a[i][1]+a[j][1])/2,yy=(a[i][2]+a[j][2])/2;

maxn=(a[i][1]-xx)*(a[i][1]-xx)+(a[i][2]-yy)*(a[i][2]-yy);

tot=0;

for (k=1;k<=n;k++)

if ((a[k][1]-xx)*(a[k][1]-xx)+(a[k][2]-yy)*(a[k][2]-yy)<=maxn) tot++;

if (tot>=m) 

if (sqrt((a[i][1]-a[j][1])*(a[i][1]-a[j][1])+(a[i][2]-a[j][2])*(a[i][2]-a[j][2]))/2<ans)

ans=sqrt((a[i][1]-a[j][1])*(a[i][1]-a[j][1])+(a[i][2]-a[j][2])*(a[i][2]-a[j][2]))/2;

}

printf("%.8f",ans);

return 0;

 

}

T3   不会写啊!!!!

 

 

接下来是题目的标准题解:

                  省选模拟题 by yqc

  注:如果你看过类似的题不要惊讶,因为这是以前看的论文题不会做的,但是很简单的。

T1

henpecked

这是一道很简单的题目所以直接出在第一题了

我们首先发现只有询问操作所以我们可以直接离线操作,将询问按照端点排序

接下来我们看到数据范围hi<=10000所以我们将询问分成两种情况处理

p<=100

这时我们可以用f[i][j]表示mod i=j的数有多少个

此时我们所需要统计的就是将r时的值减去l-1时的值可以很容易求出

p>=100

我们可以用f1[i]表示为i的数有多少个

我们只需统计f1[k]+f1[k+1*p]+f1[k+2*p]。。。我们再减去l-1时所得到的值就可以了

 

T2

fagttering

暴力:

首先我们考虑暴力怎么写,是不是枚举两个点在圆上(思考为什么不是三个或两个)

对于每两个给定点,试探所有可能的圆,分为以下两种情况:

    I) 以该两点连线为圆的直径

    II)这两点与其他N-2个点分别组成圆

通过解方程组得出圆心坐标及半径,并检查给定点集在圆内的点的数目

算法分析:

取任意两点,复杂度为O(N2)

求出所有可能的圆,复杂度为O(N)

对于任一个圆求在圆中的点的数目O(N)

算法的总复杂度:O(N4)

显然复杂度不正确,那么接下来怎么做?

正解:

接下来我们首先看一下题目,我们发现其实R是可以二分的,二分性显然可证。

那么我们应该怎么验证和确定的R的正确性呢?

技术分享

我们可以记得在不久前有一道题是将两个圆是否相交投影到了一个半径上,那么我们这道题我们假设确定了一个点一定在圆上,那么我们将每一个圆投影到这个半径上然后扯开,就转技术分享
化为了在一个线段上被多条线段最大覆盖量,显然可以(N2logn

所以总复杂度为(N2lognlogmaxR

其实也是到水题毕竟以前有接触过啊!

 

T3

rectangles

基本上就是裸的暴力题。

将矩形扣出来的方法有太多种 最后的二分图或者费用流就是一个模板所以大家如果想练代码能力的话还是可以打的。

这道题其实只是为了补充算法的多样性其实也是一道水题。

首先我们看到一一对应关系首先就可以想到网络流和二分图。

然后我们可以发现一个性质,对于每一个可以代表军区的矩形内部是没有比他小的矩形的否则选比他小的更优。

然后我们呢可以将每一个不包含其他矩形的矩形给扣出来然后,将其对应的军区连线,然后跑一边带权二分图,或者费用流就可以完美解决这道题了。

 

 

寄语:首先我是学弱,其次我没有卡常数,然后没有鬼畜题,最后没有防ak题,所以如果有人AK或者抱怨题目鬼畜,请去“自尽”。

 

 

最后说一句:虐场快乐!

 保护家园

3.25考试(hnoi难度)----神奇的一日游

标签:

原文地址:http://www.cnblogs.com/Dragon-Light/p/5323830.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!