老规矩,程序放在最后。
第一题 油滴扩展
【题目描述】
一个长方形的盒子。最多有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;
}