UVA11572 唯一的雪花 Unique Snowflakes
题目描述
企业家 Emily 有一个很酷的主意:把雪花包起来卖。她发明了一台机器,这台机器可以捕捉飘落的雪花,并把它们一片一片打包进一个包裹里。一旦这个包裹满了,它就会被封上送去发售。
Emily 的公司的口号是"把独特打包起来",为了实现这一诺言,一个包裹里不能有两片一样的雪花。不幸的是,这并不容易做到,因为实际上通过机器的雪花中有很多是相同的。Emily 想知道这样一个不包含两片一样的雪花的包裹最大能有多大,她可以在任何时候启动机器,但是一旦机器启动了,直到包裹被封上为止,所有通过机器的雪花都必须被打包进这个包裹里,当然,包裹可以在任何时候被封上。
输入格式
第一行是测试数据组数 T,对于每一组数据,第一行是通过机器的雪花总数 n(n≤106),下面 n 行每行一个在 [0,109] 内的整数,标记了这片雪花,当两片雪花标记相同时,这两片雪花是一样的。
输出格式
对于每一组数据,输出最大包裹的大小。
显示翻译
题意翻译
输入输出样例
输入 #1复制
1
5
1
2
3
2
1
输出 #1复制
3
实现代码:
cpp
#include<cstdio>
#include<map>
using namespace std;
map<int,int> snow;
int T,n,ans,last,a;
int main()
{
for(scanf("%d",&T);T--;printf("%d\n",ans))
{
snow.clear();
scanf("%d",&n);
last=ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(snow[a]>last)last=snow[a];
printf("%d\n",snow[a]);
ans=max(ans,i-last);
snow[a]=i;
}
}
return 0;
}
P4653 [CEOI 2017] Sure Bet
题目描述
现在有 n 个 A 类灯泡和 n 个 B 类灯泡,每个灯泡都有各自的权值。
我们将这些灯泡分为 n 组,每组包含一个来自 A 类的灯泡和一个来自 B 类的灯泡。
你可以从中选取任意个灯泡,每选取一个灯泡需要花费 1 的代价。
在你选取完之后,系统会随机在 A 类和 B 类中选择一个类型,并点亮那一类的所有灯泡。你选取的每个点亮的灯泡会给你带来等于它权值的收益。
最终收益相当于你点亮灯泡获得的总收益 减去你选取灯泡的代价。
现在请你合理选取灯泡,以最大化可能的最小最终收益。你只需要求出来这个最终收益即可。
输入格式
第一行一个正整数 n ,表示灯泡的组数。
接下来 n 行每行两个空格隔开的实数 Ai,Bi。分别表示属于这组的 A 灯泡和 B 灯泡的权值。输入的实数不会超过四位小数。
输出格式
输出最大化的最小可能收益,请输出到小数点后恰好四位。
输入输出样例
输入 #1复制
4
1.4 3.7
1.2 2
1.6 1.4
1.9 1.5
输出 #1复制
0.5000
说明/提示
样例解释
最优策略是选择第一组的 B 灯泡和第三组的 A 灯泡和第四组的 A 灯泡:
- 如果 B 类灯泡被点亮,收益是 3.7−3=0.7。
- 如果 A 类灯泡被点亮,收益是 1.6+1.9−3=0.5 。
最小可能收益是 0.5。
数据范围
对于所有测试点,有 1.0≤Ai,Bi≤1000.0,0≤n≤105。
实现代码:
cpp
#include<bits/stdc++.h>
using namespace std;
int n;
double A[100001],B[100001],ans;
bool visit[100001][2];
bool cmp(double a,double b)
{return a>b;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) cin>>A[i]>>B[i];
sort(A+1,A+n+1,cmp);
sort(B+1,B+n+1,cmp);
double a=0.0,b=0.0;
for(double i=1,j=1;i<=n && j<=n;)
{
int x=i,y=j;
a+=A[x]*double(!visit[x][0]);
b+=B[y]*double(!visit[y][1]);
visit[x][0]=visit[y][1]=1;
ans=max(ans,min(a-i-j,b-i-j));
if(a>=b) j++;
if(a<=b) i++;
}
printf("%.4lf",ans);
return 0;
}
P3143 [USACO16OPEN] Diamond Collector S
题目描述
奶牛 Bessie 一直喜欢闪闪发光的物体,她最近在业余时间开始了一项爱好------挖掘钻石!她收集了 N 颗大小各不相同的钻石(N≤5×104),并希望将它们中的一部分放在谷仓里的两个展示柜中展示。
由于 Bessie 希望每个展示柜中的钻石大小相对接近,她决定如果两颗钻石的大小相差超过 K,就不能将它们放在同一个展示柜中(如果两颗钻石的大小相差恰好为 K,则可以将它们一起展示在同一个展示柜中)。给定 K,请帮助 Bessie 确定她可以在两个展示柜中一起展示的最大钻石数量。
输入格式
输入文件的第一行包含 N 和 K(0≤K≤109)。
接下来的 N 行每行包含一个整数,表示一颗钻石的大小。所有钻石的大小均为正数且不超过 109。
输出格式
输出一个正整数,表示 Bessie 可以在两个展示柜中一起展示的最大钻石数量。
显示翻译
题意翻译
输入输出样例
输入 #1复制
7 3
10
5
1
12
9
5
14
输出 #1复制
5
实现代码:
cpp
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k,a[50005],c[50005],r=2,ma,ans;
int main(){
scanf("%d %d",&n,&k);
a[n+1]=2100000000;
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(int i=1;i<=n;++i){
while(a[r]<=a[i]+k)r++;
c[r]=max(r-i,c[r]);
ma=max(ma,c[i]);
ans=max(ans,ma+r-i);
}
printf("%d",ans);
return 0;
}
P7910 [CSP-J 2021] 插入排序
题目描述
插入排序是一种非常常见且简单的排序算法。小 Z 是一名大一的新生,今天 H 老师刚刚在上课的时候讲了插入排序算法。
假设比较两个元素的时间为 O(1),则插入排序可以以 O(n2) 的时间复杂度完成长度为 n 的数组的排序。不妨假设这 n 个数字分别存储在 a1,a2,...,an 之中,则如下伪代码给出了插入排序算法的一种最简单的实现方式:
这下面是 C/C++ 的示范代码:
for (int i = 1; i <= n; i++)
for (int j = i; j >= 2; j--)
if (a[j] < a[j-1]) {
int t = a[j-1];
a[j-1] = a[j];
a[j] = t;
}
这下面是 Pascal 的示范代码:
for i:=1 to n do
for j:=i downto 2 do
if a[j]<a[j-1] then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
end;
为了帮助小 Z 更好的理解插入排序,小 Z 的老师 H 老师留下了这么一道家庭作业:
H 老师给了一个长度为 n 的数组 a,数组下标从 1 开始,并且数组中的所有元素均为非负整数。小 Z 需要支持在数组 a 上的 Q 次操作,操作共两种,参数分别如下:
1 x v:这是第一种操作,会将 a 的第 x 个元素,也就是 ax 的值,修改为 v。保证 1≤x≤n,1≤v≤109。注意这种操作会改变数组的元素,修改得到的数组会被保留,也会影响后续的操作。
2 x:这是第二种操作,假设 H 老师按照上面的伪代码 对 a 数组进行排序,你需要告诉 H 老师原来 a 的第 x 个元素,也就是 ax,在排序后的新数组所处的位置。保证 1≤x≤n。注意这种操作不会改变数组的元素,排序后的数组不会被保留,也不会影响后续的操作。
H 老师不喜欢过多的修改,所以他保证类型 1 的操作次数不超过 5000。
小 Z 没有学过计算机竞赛,因此小 Z 并不会做这道题。他找到了你来帮助他解决这个问题。
输入格式
第一行,包含两个正整数 n,Q,表示数组长度和操作次数。
第二行,包含 n 个空格分隔的非负整数,其中第 i 个非负整数表示 ai。
接下来 Q 行,每行 2∼3 个正整数,表示一次操作,操作格式见【题目描述】。
输出格式
对于每一次类型为 2 的询问,输出一行一个正整数表示答案。
输入输出样例
输入 #1复制
3 4
3 2 1
2 3
1 3 2
2 2
2 3
输出 #1复制
1
1
2
说明/提示
【样例解释 #1】
在修改操作之前,假设 H 老师进行了一次插入排序,则原序列的三个元素在排序结束后所处的位置分别是 3,2,1。
在修改操作之后,假设 H 老师进行了一次插入排序,则原序列的三个元素在排序结束后所处的位置分别是 3,1,2。
注意虽然此时 a2=a3,但是我们不能将其视为相同的元素。
【样例 #2】
见附件中的 sort/sort2.in 与 sort/sort2.ans。
该测试点数据范围同测试点 1∼2。
【样例 #3】
见附件中的 sort/sort3.in 与 sort/sort3.ans。
该测试点数据范围同测试点 3∼7。
【样例 #4】
见附件中的 sort/sort4.in 与 sort/sort4.ans。
该测试点数据范围同测试点 12∼14。
【数据范围】
对于所有测试数据,满足 1≤n≤8000,1≤Q≤2×105,1≤x≤n,1≤v,ai≤109。
对于所有测试数据,保证在所有 Q 次操作中,至多有 5000 次操作属于类型一。
各测试点的附加限制及分值如下表所示。
| 测试点 | n≤ | Q≤ | 特殊性质 |
|---|---|---|---|
| 1∼4 | 10 | 10 | 无 |
| 5∼9 | 300 | 300 | 无 |
| 10∼13 | 1500 | 1500 | 无 |
| 14∼16 | 8000 | 8000 | 保证所有输入的 ai,v 互不相同 |
| 17∼19 | 8000 | 8000 | 无 |
| 20∼22 | 8000 | 2×105 | 保证所有输入的 ai,v 互不相同 |
| 23∼25 | 8000 | 2×105 | 无 |
附件下载
sort.zip19.25KB
实现代码:
cpp
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=8005;
int n,q;
int t[MAXN];
struct node{
int pre,id;
}a[MAXN];
bool cmp(node x,node y){
if(x.pre!=y.pre) return x.pre<y.pre;
return x.id<y.id;
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].pre);
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
t[a[i].id]=i;
for(int i=1;i<=q;i++){
int opt,x,v;
scanf("%d",&opt);
if(opt==1){
scanf("%d%d",&x,&v);
a[t[x]].pre=v;
for(int j=n;j>=2;j--)
if(cmp(a[j],a[j-1])){
node kkksc03=a[j];
a[j]=a[j-1];
a[j-1]=kkksc03;
}
for(int j=2;j<=n;j++)
if(cmp(a[j],a[j-1])){
node kkksc03=a[j];
a[j]=a[j-1];
a[j-1]=kkksc03;
}
for(int i=1;i<=n;i++)
t[a[i].id]=i;
}
else{
scanf("%d",&x);
printf("%d\n",t[x]);
}
}
return 0;
}
P1578 [WC2002] 奶牛浴场
题目描述
由于 John 建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减少。为了讨好奶牛,John 决定在牛场中建造一个大型浴场。但是 John 的奶牛有一个奇怪的习惯,每头奶牛都必须在牛场中的一个固定的位置产奶,而奶牛显然不能在浴场中产奶,于是,John 希望所建造的浴场不覆盖这些产奶点。这回,他又要求助于 Clevow 了。你还能帮助 Clevow 吗?
John 的牛场和规划的浴场都是矩形。浴场要完全位于牛场之内,并且浴场的轮廓要与牛场的轮廓平行或者重合。浴场不能覆盖任何产奶点,但是产奶点可以位于浴场的轮廓上。
Clevow 当然希望浴场的面积尽可能大了,所以你的任务就是帮她计算浴场的最大面积。
输入格式
输入文件的第一行包含两个整数 L 和 W,分别表示牛场的长和宽。
文件的第二行包含一个整数 n,表示产奶点的数量。
以下 n 行每行包含两个整数 x 和 y,表示一个产奶点的坐标。
输出格式
输出文件仅一行,包含一个整数 S,表示浴场的最大面积。
输入输出样例
输入 #1复制
10 10
4
1 1
9 1
1 9
9 9
输出 #1复制
80
说明/提示
对于所有数据,0≤n≤5×103,1≤L,W≤3×104。所有产奶点都位于牛场内,即:0≤x≤L,0≤y≤W。
感谢 @凯瑟琳98 提供了 4 组 hack 数据。
实现代码:
cpp
#include<bits/stdc++.h>
using namespace std;
int read()
{
int sum = 0 , f = 1;
char c = getchar();
while(c < '0' or c > '9')
{
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' and c <= '9')
{
sum = (sum << 1) + (sum << 3) + c - '0';
c = getchar();
}
return sum * f;
}
struct S{
int x , y;
}s[5010];
bool cmp1(S a , S b)
{
if(a.x != b.x) return a.x < b.x;
else return a.y < b.y;
}
bool cmp2(S a , S b)
{
if(a.y != b.y) return a.y < b.y;
else return a.x < b.x ;
}
int l , w , n , ans;
int main()
{
l = read() , w = read() , n = read();
for(int i = 1; i <= n; i ++) s[i].x = read() , s[i].y = read();
s[++ n].x = 0 , s[n].y = 0;
s[++ n].x = 0 , s[n].y = w;
s[++ n].x = l , s[n].y = 0;
s[++ n].x = l , s[n].y = w;
int x1 , x2 , y1 , y2;
sort(s + 1 , s + n + 1 , cmp1);
for(int i = 1; i <= n; i ++)
{
x1 = s[i].x , y1 = 0 , y2 = w;
for(int j = i + 1; j <= n; j ++)
{
x2 = s[j].x;
ans = max(ans , (x2 - x1) * (y2 - y1));
if(s[j].y < s[i].y) y1 = max(y1 , s[j].y);
else y2 = min(y2 , s[j].y);
}
}
for(int i = n; i >= 1; i --)
{
x1 = s[i].x , y1 = 0 , y2 = w;
for(int j = i - 1; j >= 1; j --)
{
x2 = s[j].x;
ans = max(ans , (x1 - x2) * (y2 - y1));
if(s[j].y < s[i].y) y1 = max(y1 , s[j].y);
else y2 = min(y2 , s[j].y);
}
}
sort(s + 1 , s + n + 1 , cmp2);
for(int i = 1; i <= n - 1; i ++)
{
ans = max(ans , l * (s[i + 1].y - s[i].y));
}
printf("%d" , ans);
return 0;
}