您的位置:首页 > 其它

2015-08-13NOIP模拟赛

2015-08-13 23:31 260 查看
2015-08-13NOIP模拟赛

今天有考试,我又一次华丽丽滴跪了……

第一题:

Description

lahub是一个旅行者的粉丝,他想成为一个真正的旅行者,所以他计划开始一段旅行。lahub想去参观n个目的地(都在一条直道上)。lahub在起点开始他的旅行。第i个目的地和起点的距离为ai千米(ai为非负整数)。不存在两个目的地和起点的距离相同。

从第i个目的地走到第j个目的地所走的路程为 |ai-aj|千米。我们把参观n个目的地的顺序称作一次“旅行”。lahub可以参观他想要参观的任意顺序,但是每个目的地有且只能被参观一次(参观顺序为n的排列)。

lahub把所有可能的“旅行”都写在一张纸上,并且记下每个“旅行”所要走的路程。他对所有“旅行”的路程之和的平均值感兴趣。但是他觉得计算太枯燥了,所以就向你寻求帮助。

Input

第一行一个正整数n。

第二行n个非负整数a1,a2,....,an(1≤ai≤10^7)。

Output

两个整数,答案用最简分数形式输出,第一个为分子,第二个为分母。

Sample Input

3

2 3 5

Sample Output

22 3

Sample Explanation

样例有6种可能的旅行:

[2, 3, 5]: 该“旅行”的路程:|2 – 0| + |3 – 2| + |5 – 3| = 5;

[2, 5, 3]: |2 – 0| + |5 – 2| + |3 – 5| = 7;

[3, 2, 5]: |3 – 0| + |2 – 3| + |5 – 2| = 7;

[3, 5, 2]: |3 – 0| + |5 – 3| + |2 – 5| = 8;

[5, 2, 3]: |5 – 0| + |2 – 5| + |3 – 2| = 9;

[5, 3, 2]: |5 – 0| + |3 – 5| + |2 – 3| = 8;

答案为 1/6 * (5+7+7+8+9+8)=44/6=22/3。

Hint

30%的数据: n≤10;

50%的数据: n≤1000;

100%的数据: n≤100000。

Analyse

首先裸暴力过30%应该是OK滴。

对于本题我们先把道路分段,统计每段出现次数:

1: 1

2: 2 3

3: 6 12 10

4: ……

我们通过观察发现第N行第i个数为:

(N-1)!*(N+1-i)*(2*N-1)然后不说了,暴力跑一趟

TIP:数据要先排序。



第二题:


Description

众所周知Kelukin是一名宇宙级土豪,他公司的生意自然是相当的好。

现在他手上有n份工作要完成,每一份工作有一个土豪指标Ak。由于这些工作数量太多,Kelukin又懒,所以他无法一个人完成,他需要雇用很多工人来帮忙。可是Kelukin十分小气,经常克扣工资,因此没有多少人愿意帮他。而愿意帮他的那些工人各个都是奇葩,而且他们非常精明,按工作量收费,小于k份的工作量他们是不会去做的,而他们完成一次工作要额外收C元。一个工人最多做一次工作。

Kelukin表示那些工作之间有很多是类似的,完成了第一份第二份能很快扫完,因此他这么规定一个工人的报酬:若工人所做的工作的土豪指标为(T1,T2,T3,T4……,Tm),则他的报酬为C+(maxTi-minTi)^2,1≤i≤m,m≥k。

作为Kelukin的贴身秘书,你有义务告诉他为了完成这n份工作最少要花多少钱。当然,Kelukin非常的小气,他是不会给你工资的。

Input

第一行三个正整数n、k、C(1≤k≤n≤10^6,0≤C≤10^9),之间用一个空格隔开。

第二行为n个正整数,描述n份工作的土豪指标(0<Ak≤10^9),之间用一个空格隔开。

Output

一行仅一个整数,表示Kelukin最少需要支付的工资(保证答案不大于10^17)。

Sample Input

2 1 1

2 4

Sample Output

2

Sample Explanation

如果分给一个工人做,收费为 1 + (4 – 2) ^2 = 5。

如果分给两个工人作,收费为 1 + 1 = 2。

所以最小收费为2。

Hint

50%的数据:N≤1000。

70%的数据:N≤50000。

100%的数据:N≤1000000。

Analyse

50%的点可以裸DP跑。

F[i]=max{F[j]+(A[i]-A[j+1])^2+C} (j-i>=K)

根据数学分析发现本题决策明显具有单调性:于是70%的点有着落了,A。

至于满分算法,很明显采用传说中的斜率优化

F[i]=max{F[j]+(A[i]-A[j+1])^2+C} (j-i>=K)

=>F[i]=max {F[j]+A[j+1]^2-2*A[i]*A[j+1]}+C+A[i]*A[i]

用单调队列记录入队元素,O(n)解决。(考试时评测机奇快,O(n^2-RP) 的也能过!!)

第三题:

Description

刚拿到驾照的KJ 总喜欢开着车到处兜风,玩完了再把车停到阿Q的停车场里,虽然她对自己停车的水平很有信心,但她还是不放心其他人的停车水平,尤其是Kelukin。于是,她每次都把自己的爱车停在距离其它车最远的一个车位。KJ 觉得自己这样的策略非常科学,于是她开始想:在一个停车场中有一排车位,从左到右编号为 1 到 n,初始时全部是空的。有若干汽车,进出停车场共 m 次。对于每辆进入停车场的汽车,会选择与其它车距离最小值最大的一个车位,若有多个符合条件,选择最左边一个。KJ
想着想着就睡着了,在她一旁的Kelukin想帮她完成这个心愿,但是他又非常的懒,不愿意自己动手,于是就把这个问题就留给了你:在KJ 理想的阿 Q 的停车场中,给你车辆进出的操作序列,依次输出每辆车的车位编号。

Input

第一行,两个整数 n 和 m,表示停车场大小和操作数;

接下来 m 行,每行两个整数,F 和 x

F 是 1 表示编号为 x 的车进停车场;

F 是 2 表示编号为 x 的车出停车场;

保证操作合法,即:出停车场的车一定目前仍在停车场里;停车场内的车不会超过 n;

Output

对于所有操作 1,输出一个整数,表示该车车位的编号。

Sample Input

7 11

1 15

1 123123

1 3

1 5

2 123123

2 15

1 21

2 3

1 6

1 7

1 8

Sample Output

1

7

4

2

7

4

1

3

Hint

30%的数据:n≤1000 ,m≤1000;

60%的数据:n≤200000,m≤2000;

100%的数据:n,m≤200000,车的编号小于等于 10^6。

Analyse

30%的数据,不明觉厉,这都不过就白混了。
60%的数据有两种方式:1.用对记录每个可能的停车点坐标
2. 用链表记录当前所有车的位置+暴力查找
对于这题链表的优势就体现了出来:插入删除奇快。
100%的数据同样还是链表,可是我们发现链表的查找极度耽误时间,这样……我们用Heap可以优化。
STL大法好。。。

代码:
T1:
#include <iostream>
#include <vector>
#include <bitset>
#include <cmath>
#include <iomanip>
#include <string>
#include <string.h>
#include <time.h>
#include <memory.h>
#include <stdio.h>
#include <cmath>
#include <stdlib.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <cstdio>
#include <climits>

#define intmin -2147483640
#define intmax 2147483640

using namespace std;

const int MAXN=100010;

typedef unsigned long long LL;

int N,A[MAXN];
LL AnsFZ,ANSFM;

inline LL GCD (LL a,LL b) {if (a%b==0)return b ;else return GCD (b,a%b);}

int main()
{
scanf ("%d",&N);
LL tmp=1;
int i;
for (i=1;i<=N;i++)
scanf ("%d",&A[i]);
sort(A+1,A+1+N);
for (i=1;i<=N;i++)
AnsFZ+=(A[i]-A[i-1])*tmp*(N+1-i),
tmp+=2;
ANSFM=N;
tmp=GCD (AnsFZ,ANSFM);
cout<<AnsFZ/tmp<<" "<<ANSFM/tmp<<endl;
return 0;
}


T2:
#include <iostream>
#include <vector>
#include <bitset>
#include <cmath>
#include <iomanip>
#include <string>
#include <string.h>
#include <time.h>
#include <memory.h>
#include <stdio.h>
#include <cmath>
#include <stdlib.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <cstdio>
#include <climits>

#define intmin -2147483640
#define intmax 214748364000ll

using namespace std;

const int MAXN=3000010;

typedef long long LL;

int N,K,C;
int AK[MAXN];
LL F[MAXN];
LL Q[MAXN],front=1,rear=1;

inline LL DP1num (int j,int k) {return (F[j]-F[k]+AK[j+1]*AK[j+1]-AK[k+1]*AK[k+1]);}
inline int DP2num (int j,int k) {return (AK[j+1]-AK[k+1]);}
inline bool Judge (int i,int j,int k){return (LL) DP1num(j,k)<=DP2num(j,k)*(2*AK[i]);}

void init ()
{
scanf ("%d%d%d",&N,&K,&C);
int i;
for (i=1;i<=N;i++)
scanf ("%d",&AK[i]),F[i]=intmax;
sort (AK+1,AK+N+1);
}

LL FZ (int st,int ed)
{
if (ed-st+1==K) return (LL)C+(AK[st]-AK[ed])*(AK[st]-AK[ed]);
if (st>ed || ed-st+1<K || st+K>N || ed-K<1) return intmax;
int i;LL ans=C+(AK[ed]-AK[st])*(AK[ed]-AK[st]);
for (i=st+K-1;i<=ed-K;i++)
ans=min (ans,FZ(st,i)+FZ(i+1,ed));
return ans;
}

void DP ()
{
int i,j;
for(i = 1; i <= K - 1; ++i) F[i] = intmax;
for (i=K;i<=N;i++)
{
if(i - K == 0 || i - K >= K) {
while (front<rear && DP1num(i-K,Q[rear-1])*DP2num(Q[rear-1],Q[rear-2])>=DP1num(Q[rear-1],Q[rear-2])*DP2num(i-K,Q[rear-1])) rear--;
Q[rear++] = i - K;
}
while (front<rear && Judge(i, Q[front], Q[front + 1])) front++;
F[i]=F[Q[front]]+C+(LL)(AK[i]-AK[Q[front]+1])*(AK[i]-AK[Q[front]+1]);
for(j = front; j < rear; ++j) cout << Q[j] << " "; cout << endl;
}
cout<<F
;
}

int main ()
{
init ();
DP ();
return 0;
}


T3:
30分:
#include <iostream>
#include <vector>
#include <bitset>
#include <cmath>
#include <iomanip>
#include <string>
#include <string.h>
#include <time.h>
#include <memory.h>
#include <stdio.h>
#include <cmath>
#include <stdlib.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <cstdio>
#include <climits>

#define intmin -2147483640
#define intmax 21474836400000ll

using namespace std;

const int MAXN=20000;

int car[MAXN];
int n,m;

int workin (int ks)
{
int i,j=-MAXN,k;
for (i=1;i<=n;i++)
if (car[i]!=0)
j=intmin;
if (j!=intmin) {car[1]=ks;return 1;}

int maxn=0,pos;
for (i=1;i<=n;i++)
{
if (car[i]) continue;
for (j=i-1;!car[j] && j>=1;j--);
for (k=i+1;!car[k] && k<=n;k++);

if (k==n+1)
{if (maxn<i-j) maxn=i-j,pos=i;}
else
if (j==0)
{if (maxn<k-i) maxn=k-i,pos=i;}
else
if (k-i<i-j)
{if (maxn<k-i) maxn=k-i,pos=i;}
else
{if (maxn<i-j) maxn=i-j,pos=i;}
}
car[pos]=ks;
return pos;
}

void workout (int k)
{
int i,j;
for (i=1;i<=n;i++)
if (car[i]==k)
car[i]=0;
}

void init ()
{
scanf ("%d%d",&n,&m);
int x,k,i;
for (i=1;i<=m;i++)
{
scanf ("%d%d",&x,&k);
if (x==1)
printf ("%d\n",workin(k));
else
workout(k);
}
}

int main ()
{
init ();
}


100分(可惜有错,求大神修改):
#include <iostream>
#include <vector>
#include <bitset>
#include <cmath>
#include <iomanip>
#include <string>
#include <string.h>
#include <time.h>
#include <memory.h>
#include <stdio.h>
#include <cmath>
#include <stdlib.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <cstdio>
#include <climits>

#define intmin -2147483640
#define intmax 2147483640

using namespace std;

inline int abs (int x){return x>0?x:-x;}

typedef struct Node_Tp
{
Node_Tp *pi,*ne;
int id,pos;
}nodes;

typedef struct Queue_Tp
{
int lcar,rcar;
int len;
void update (){len=rcar-lcar;}
bool operator < (const Queue_Tp &Y)const
{return len>Y.len;}
}que;

nodes *Head;
int N;
priority_queue<que> Q;

int Workin (int x)
{
Node_Tp *p;
que tmp;
p=Head->ne;
if (p==NULL)
{
p=new Node_Tp;
p->pi=Head;p->ne=NULL;
p->id=x,p->pos=1;
Head->ne=p;
tmp.lcar=1,tmp.rcar=N;tmp.len=N-1;
Q.push(tmp);
return p->pos;
}

tmp=Q.top ();Q.pop ();
int findn=(tmp.lcar+tmp.rcar)>>1;
Node_Tp *q;
q=new Node_Tp;
q->id=x,q->pos=findn;

que tmpp;

while (p->ne!=NULL)
{
if (findn>p->pos && findn<(p->ne->pos))
{
q->pi=p,q->ne=p->ne,p->ne->pi=q,p->ne=q;
tmpp.lcar=q->pi->pos,tmpp.rcar=q->pos;
tmpp.update(),Q.push (tmpp);
tmpp.lcar=q->pos,tmpp.rcar=q->ne->pos;
tmpp.update(),Q.push (tmpp);
return p->pos;
}
p=p->ne;
}

if (Head->pos-1>N-p->pos)
{
q->pi=Head,q->ne=Head->ne;
q->pos=1;
tmpp.lcar=0,tmpp.rcar=q->ne->pos;
tmpp.len=p->pos-1,Q.push (tmpp);
Head->ne->pi=q,Head->ne=q;
return 1;
}
else
{
q->pi=p,q->ne=NULL;
q->pos=N;
tmpp.lcar=p->pos,tmpp.rcar=N+1;
tmpp.len=N-p->pos,Q.push (tmpp);
p->ne=q;
return N;
}
}

void Workout (int x)
{
Node_Tp *p;
que tmp;
p=Head->ne;

while (p->ne!=NULL)
{
if (p->id==x)
{
p->pi->ne=p->ne;
p->ne->pi=p->pi;
break;
}
p=p->ne;
}
while (!Q.empty ())Q.pop();
p=Head->ne;
while (p->ne!=NULL)
{
tmp.lcar=p->pos,tmp.rcar=p->ne->pos;
tmp.update();
Q.push (tmp);
}
tmp.lcar=1,tmp.rcar=Head->ne->pos;
tmp.update();
tmp.lcar=p->pos,tmp.rcar=N;
tmp.update();
}

void init ()
{
int M,i,x,y;
Head=new Node_Tp;
Head->ne=NULL;
scanf ("%d%d",&N,&M);
for (i=1;i<=M;i++)
{
scanf ("%d%d",&x,&y);
if (x==1)
printf ("%d\n",Workin(y));
else
Workout(y);
}
}

int main ()
{
init ();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: