老规矩,程序放在最后。
第一题 油滴扩展
【题目描述】
一个长方形的盒子。最多有N个相异的点。每个点可以放上一个油滴,油滴会扩展,知道接触到其他油滴或者盒子边缘。请确定一种放置顺序,使得油滴占据的总面积最大。
【输入格式】
第一行一个整数N。
第二行为长方形边框的一个顶点和其对角顶点的坐标x,y,x’,y’。
接下来的N行,每行两个整数xi,yi,表示盒子里的点。
保证所有的整数都在[-1000,1000]范围。
【输出格式】
一行一个整数,长方形盒子剩余的最小空间(结果四舍五入)。
【样例输入】
2
0 0 10 10
3 3
7 7
【样例输出】
50
【分析】
递归搜索。
第二题 数列
直接传送门。
http://www.cnblogs.com/sephirothlee/archive/2010/10/08/1846073.html
第三题 SOFTWARE
再次传送门。
http://www.cnblogs.com/sephirothlee/archive/2010/10/09/1846498.html
第四题 黑匣子
【题目描述】
black box是一种原始的数据库。他可以储存一个整数数组,还有一个特别的变量i。最开始的时候black box是空的,而i等于0。这个black box要处理一串命令。
命令只有两种:
ADD(X):把X元素放进black box中;
GET:i加1,然后输出black box中第i小的数。
现在用两个整数数组来表示命令串:
1.A(1),A(2)……A(M):一串将要被放进black box中的元素。每个书都是绝对值不超过2000000000的整数,M<=200000。
2.U(1),U(2)……U(N):表示第U(J)个元素被放入black box中后就出现一个GET命令。输入数据不用判错。
【输入格式】
第一行:两个整数,M,N。
第二行:M个整数,表示A(1)……A(M)。
第三行:N个整数,表示U(1)……U(N)。
【输出格式】
输出根据命令串所得出的输出串,一个数字一行。
【输入样例】
7 4
3 1 –4 2 8 –1000 2
1 2 6 6
【输出样例】
3
3
1
2
【数据范围】
对于30%的数据,M<=10000;
对于50%的数据,M<=100000;
对于100%的数据,M<=200000。
【分析】
一个treap解决。
代码
第一题
#include <stdio.h> #include <math.h> #define MAXN 10 #define pi 3.1415926535 struct ss { int x,y; double r; bool v; } a[MAXN]; int n; double maxs; int xx[2],yy[2]; double abs(double x) { if (x < 0) x = 0 - x; return x; } double dis(double x1,double y1,double x2,double y2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } int si(double x) { int te = (int) x; if (te + 0.5 > x) return te; else return te + 1; } void find(int x) { if (x > n) { double tem = 0; for (int i = 1;i <= n;++i) tem += pi * a[i].r * a[i].r; if (tem > maxs) maxs = tem; return; } for (int i = 1;i <= n;++i) if (!a[i].v) { double temr = 1000000010; for (int j = 1;j <= n;++j) if (a[j].v) { double temp = dis(a[j].x,a[j].y,a[i].x,a[i].y) - a[j].r; if (temp < temr) temr = temp; } for (int j = 0;j < 2;++j) { if (abs(xx[j] - a[i].x) < temr) temr = abs(xx[j] - a[i].x); if (abs(yy[j] - a[i].y) < temr) temr = abs(yy[j] - a[i].y); } if (temr < 0) temr = 0; a[i].v = 1; a[i].r = temr; find(x + 1); a[i].v = 0; } } int main() { freopen("box.in","r",stdin); freopen("box.out","w",stdout); scanf("%d",&n); for (int i = 0;i < 2;++i) scanf("%d%d",&xx[i],&yy[i]); for (int i = 1;i <= n;++i) scanf("%d%d",&a[i].x,&a[i].y); find(1); double ans = abs(xx[0] - xx[1]) * abs(yy[0] - yy[1]); ans = ans - si(maxs); printf("%d\n",(int)ans); return 0; }
第二题
#include <stdio.h> #include <iostream> #define MAXN 1010 using namespace std; int f[MAXN][MAXN][2],a[MAXN],ans,n; bool have[MAXN][MAXN]; void find(int x,int y) { if (have[x][y]) return; if ((y > x) || (y < 0) || (x < 0)) return; have[x][y] = 1; find(x - 1,y - 1); find(x - 1,y); if (x - 1 < 0) return; f[x][y][0] = f[x - 1][y][0]; if ((y - 1 >= 0) && (f[x - 1][y][1] > f[x][y][0])) f[x][y][0] = f[x - 1][y][1]; bool t = (a[x] == (x - y)); if (t) ++f[x][y][0]; if (y - 1 >= 0) f[x][y][1] = max(f[x - 1][y - 1][0],f[x - 1][y - 1][1]); } int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); scanf("%d",&n); for (int i = 1;i <= n;++i) scanf("%d",&a[i]); for (int i = 0;i <= n;++i) find(n,i); for (int i = 0;i <= n;++i) { if (f[n][i][0] > ans) ans = f[n][i][0]; if (f[n][i][1] > ans) ans = f[n][i][1]; } printf("%d\n",ans); return 0; }
第三题
#include <stdio.h> #include <string.h> #include <iostream> #define MAXN 110 using namespace std; int w[MAXN][2],f[MAXN][MAXN]; int n,m,max_time,l,r,mid; bool check(int mid) { memset(f,-1,sizeof(f)); f[0][0] = 0; for (int i = 1;i <= n;++i) for (int j = 0;j <= m;++j) { if (f[i - 1][j] < 0) continue; for (int k = 0;(j + k <= m) && (mid >= w[i][0] * k);++k) if (f[i][j + k] < f[i - 1][j] + (mid - w[i][0] * k) / w[i][1]) f[i][j + k] = f[i - 1][j] + (mid - w[i][0] * k) / w[i][1]; } return f[n][m] >= m; } int main() { freopen("software.in","r",stdin); freopen("software.out","w",stdout); scanf("%d%d",&n,&m); for (int i = 1;i <= n;++i) { scanf("%d%d",&w[i][0],&w[i][1]); if (w[i][0] > max_time) max_time = w[i][0]; if (w[i][1] > max_time) max_time = w[i][1]; } r = max_time * m; l = 1; while (l <= r) { mid = (l + r) / 2; if (check(mid)) r = mid - 1; else l = mid + 1; } printf("%d\n",l); return 0; }
第四题
#include<stdio.h> #include<stdlib.h> #define mmm 1000000 #define MAXN 200010 struct ss { int left,right,key,data,count,size; } t[mmm+1]; int n,m,x,y,tot,tott,root; int a[MAXN],u[MAXN]; void modify(int x) { t[x].size=t[t[x].left].size+t[x].count+t[t[x].right].size; } void leftrotate(int *x) { int te=t[*x].left; t[*x].left=t[te].right; t[te].right=*x; modify(*x); *x=te; modify(*x); } void rightrotate(int *x) { int te=t[*x].right; t[*x].right=t[te].left; t[te].left=*x; modify(*x); *x=te; modify(*x); } void insert(int *x,int y) { if (*x==0) { *x=++tot; t[*x].left=0; t[*x].right=0; t[*x].size=1; t[*x].count=1; t[*x].key=rand()%mmm; t[*x].data=y; } else { if (y==t[*x].data) ++t[*x].count; else if (y<t[*x].data) { insert(&t[*x].left,y); if (t[t[*x].left].key<t[*x].key) leftrotate(x); } else { insert(&t[*x].right,y); if (t[t[*x].right].key<t[*x].key) rightrotate(x); } modify(*x); } } int findkth(int x,int y) { if (y<=t[t[x].left].size) return findkth(t[x].left,y); else if (y<=t[t[x].left].size+t[x].count) return t[x].data; else return findkth(t[x].right,y-t[t[x].left].size-t[x].count); } int main() { freopen("blackbox.in","r",stdin); freopen("blackbox.out","w",stdout); scanf("%d%d",&m,&n); srand(n); for (int i = 1;i <= m;++i) scanf("%d",&a[i]); for (int i = 1;i <= n;++i) scanf("%d",&u[i]); int now = 1,get = 0,ans; for (int i = 1;i <= m;++i) { insert(&root,a[i]); while (i == u[now]) { ++now; ++get; ans = findkth(root,get); printf("%d\n",ans); } } return 0; }