2015-08-13NOIP模拟赛
2015-08-13 23:31
260 查看
2015-08-13NOIP模拟赛
今天有考试,我又一次华丽丽滴跪了……
第一题:
从第i个目的地走到第j个目的地所走的路程为 |ai-aj|千米。我们把参观n个目的地的顺序称作一次“旅行”。lahub可以参观他想要参观的任意顺序,但是每个目的地有且只能被参观一次(参观顺序为n的排列)。
lahub把所有可能的“旅行”都写在一张纸上,并且记下每个“旅行”所要走的路程。他对所有“旅行”的路程之和的平均值感兴趣。但是他觉得计算太枯燥了,所以就向你寻求帮助。
第二行n个非负整数a1,a2,....,an(1≤ai≤10^7)。
2 3 5
[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。
50%的数据: n≤1000;
100%的数据: n≤100000。
对于本题我们先把道路分段,统计每段出现次数:
1: 1
2: 2 3
3: 6 12 10
4: ……
我们通过观察发现第N行第i个数为:
(N-1)!*(N+1-i)*(2*N-1)然后不说了,暴力跑一趟
TIP:数据要先排序。
第二题:
现在他手上有n份工作要完成,每一份工作有一个土豪指标Ak。由于这些工作数量太多,Kelukin又懒,所以他无法一个人完成,他需要雇用很多工人来帮忙。可是Kelukin十分小气,经常克扣工资,因此没有多少人愿意帮他。而愿意帮他的那些工人各个都是奇葩,而且他们非常精明,按工作量收费,小于k份的工作量他们是不会去做的,而他们完成一次工作要额外收C元。一个工人最多做一次工作。
Kelukin表示那些工作之间有很多是类似的,完成了第一份第二份能很快扫完,因此他这么规定一个工人的报酬:若工人所做的工作的土豪指标为(T1,T2,T3,T4……,Tm),则他的报酬为C+(maxTi-minTi)^2,1≤i≤m,m≥k。
作为Kelukin的贴身秘书,你有义务告诉他为了完成这n份工作最少要花多少钱。当然,Kelukin非常的小气,他是不会给你工资的。
第二行为n个正整数,描述n份工作的土豪指标(0<Ak≤10^9),之间用一个空格隔开。
2 4
如果分给两个工人作,收费为 1 + 1 = 2。
所以最小收费为2。
70%的数据:N≤50000。
100%的数据:N≤1000000。
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) 的也能过!!)
第三题:
想着想着就睡着了,在她一旁的Kelukin想帮她完成这个心愿,但是他又非常的懒,不愿意自己动手,于是就把这个问题就留给了你:在KJ 理想的阿 Q 的停车场中,给你车辆进出的操作序列,依次输出每辆车的车位编号。
接下来 m 行,每行两个整数,F 和 x
F 是 1 表示编号为 x 的车进停车场;
F 是 2 表示编号为 x 的车出停车场;
保证操作合法,即:出停车场的车一定目前仍在停车场里;停车场内的车不会超过 n;
1 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8
7
4
2
7
4
1
3
60%的数据:n≤200000,m≤2000;
100%的数据:n,m≤200000,车的编号小于等于 10^6。
60%的数据有两种方式:1.用对记录每个可能的停车点坐标
2. 用链表记录当前所有车的位置+暴力查找
对于这题链表的优势就体现了出来:插入删除奇快。
100%的数据同样还是链表,可是我们发现链表的查找极度耽误时间,这样……我们用Heap可以优化。
STL大法好。。。
代码:
T1:
T2:
T3:
30分:
100分(可惜有错,求大神修改):
今天有考试,我又一次华丽丽滴跪了……
第一题:
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
32 3 5
Sample Output
22 3Sample 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 12 4
Sample Output
2Sample 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 111 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8
Sample Output
17
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 (); }
相关文章推荐
- iOS UIPopoverView的使用
- Fragment的知识总结
- Redis对于key的操作命令
- java netty socket库和自定义C#socket库利用protobuf进行通信完整实例
- TCP/IP详解学习笔记
- Linq的join后面跟多个条件
- 如何利用OpenCV自带的haar training程序训练分类器
- HDU 5387 Clock // 模拟
- 如何在一家大公司里受到重用
- 递归全排列
- 全网最全ASP.NET MVC 教程汇总
- java 中的异步回调
- 人民币阿拉伯数字转中文大写
- html学习笔记(15)
- 黑马程序员———正则表达式及其其他类
- 面向设计的半封装web组件开发(概要版)
- OpenCV训练分类器制作xml文档
- HDU 1237 简单计算器
- 使用OGG的logdump工具检查OGG trail file中存在不存在相关表的记录
- LeetCode——Count Complete Tree Nodes