2015-08-13NOIP模拟赛

来源:互联网 发布:sql server insert语句 编辑:程序博客网 时间:2024/06/07 10:52

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 2147483640using 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 214748364000llusing 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[N];}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 21474836400000llusing 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 2147483640using 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 ();}



0 0
原创粉丝点击