UPC2022暑期个人训练赛第32场
问题 A: 窨井盖
题目描述
Jzt小时候走路的时候,有一个习惯,踩着窨井盖走。(不知道有没有人小时候也有这种做法……)
踩窨井盖很爽,但是,jzt不希望走得太慢,因此,他希望每一步走过的距离的最小值最大。为了快一点走,jzt只好忍痛割爱,跳过一些窨井盖。但是,如果跳过太多,又会觉得不爽,因此,他决定,最多可以跳过M个窨井盖。
你可以认为jzt的腿无限长,不用担心一步跨不到……
输入
第一行三个数L,N,M,分别表示家的位置,有N个窨井盖,可以跳过M个窨井盖。
接下来N行,每行一个数Di,表示N个窨井盖的位置
输出
输出一行一个数,表示最小距离的最大值。
样例输入
25 5 2
2
14
11
21
17
样例输出
4
提示
样例解释:跳过位置2和位置14的窨井盖,剩下相邻的窨井盖中距离最小的是4,是17到21或者21到25
1<=L<=1,000,000,000
0<=N<=50,000
0<=M<=N
0<Di<L
50%的数据,N<=100
一开始想作差然后排个序,选第m+1个,后来发现跳过井盖后,某些差值会变大,所以这个思路不行。不行,咱就枚举试试呗,但是鉴于1e9的数据量,用二分可以解决
代码
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
int l,m,n;
int d[50005];
signed main()
{
cin>>l>>n>>m;
for(int i=1;i<=n;i++)
cin>>d[i];
d[n+1]=l;
sort(d,d+1+n);
int ll=1,r=l+1,mid;
while(ll<r)
{
mid=ll+r+1>>1;//因为mid是减一的避免死循环
int k=0,q=0;//k是最小跳过距离为m时一定跳过的井盖的数量
for(int i=1;i<=n+1;i++)
{
if(d[i]-q<mid)k++;//小于的才跳
else q=d[i];
}
if(k>m)r=mid-1;//k>m说明这个m不可行
else ll=mid;
}
cout<<ll;
return 0;
}
问题 B: 约会序列
题目描述
众所周知,HYF有很多小姊妹。
HYF的小姊妹军团共有N个人,他每天选择一个不同的MM约会。现在HYF想把未来的N天里要约会的MM做一个计划……
首先,他按照自己的标准把N个MM分成A等~Z等,当然A等是质量最好的,Z等是质量最差的(可怜的Z等MM……),然后把她们随机地排成一个队列,比如ACDBCB。HYF决定每次选择队列最前或最后的MM约会,约过的MM就从队列中删去,这样就得到一个长度为N的约会序列。不同的选择方式会得到不同的约会序列,贪心的HYF当然希望先约质量高的MM啦!所以他希望得到所有约会序列中字典序最小的那个。
请你写一个程序帮他确定这样的约会序列。
输入
第一行一个正整数N,表示一共N个MM
接下来N行,每行一个大写字母,表示队列中第i个MM的级别
输出
一行一个长度为N的字符串,表示约会序列中字典序最小的那个。
样例输入
6
A
C
D
B
C
B
样例输出
ABCBCD
提示
30%的数据,N<=20
60%的数据,N<=100
100%的数据,N<=2000
这题。一开始死活55分把我挡住了,重写了一个没想到意外过了
就是在处理相同字母时需要考虑下,之前的策略是输出一个,然后到不行(两指针相等或者字母不等时判断下),估计有bug的,后来干脆输出交给下一波循环吧,数据较小。
代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int n;
char s[20010];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>s[i];
for(int i=1,j=n;i<=j;)
{
if(s[i]<s[j])
{
cout<<s[i];
i++;
}
else if(s[i]>s[j])
{
cout<<s[j];
j--;
}
else
{
int l=i,r=j;
while(l<=r)
{
if(s[l]!=s[r])break;
l++,r--;
}
if(s[l]<s[r])
{
cout<<s[i];
i++;
}
else
{
cout<<s[j];
j--;
}
}
}
return 0;
}
问题 C: 直角三角形
题目描述
在平面直角坐标系上有N个点。
编写程序,统计出这N个点能构成多少个两直角边分别平行于坐标轴的直角三角形。
输入
输入共有两行:
第1行:输入一个整数N,(3≤N≤500,000);
第2行到N+1行:每行两个正整数X,Y(1≤X,Y≤500,000),代表点的坐标。
输出
输出只有一行,
输出直角三角形的个数。
样例输入
【样例1】
3
4 2
2 1
1 2
【样例2】
6
10 10
20 10
10 20
20 20
30 20
30 30
样例输出
【样例1】
0
【样例2】
8
提示
对于全部40%的数据,保证N≤100;
对于全部70%的数据,保证N≤10,000;
对于全部的数据,保证N≤500,000;
这个题需要坐标系画图,可以用GeoGebra
样例二
有些眼花缭乱,我们分析一下,既然是直角三角形,而且直角边平行于坐标轴,那么对于一个点(x,y)它能和它同行和同列的点组成(l-1)*(r-1)个直角三角形,对于每个点枚举相加下就OK了,此题ans开long long
代码
#include<iostream>
#include<map>
#define int long long
using namespace std;
int n,l[500001],r[500001],ans;
struct point
{
int x;int y;
}a[500001];
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%lld %lld",&a[i].x,&a[i].y);
l[a[i].x]++;
r[a[i].y]++;
}
for(int i=1;i<=n;i++)
{
int x=a[i].x,y=a[i].y;
if((l[x]>1)&&(r[y]>1))
ans=ans+(l[x]-1)*(r[y]-1);
}
cout<<ans;
return 0;
}
问题 D: 最勇敢的机器人
题目描述
机器人们都想知道谁是最勇敢的,于是它们比赛搬运一些物品。
它们到了一个仓库,里面有n个物品,每个物品都有一个价值Pi和重量Wi,但是有些物品放在一起会爆炸,并且爆炸具有传递性。(a和b会爆炸、b和c会爆炸则a和c会爆炸)机器人们可不想因此损失自己好不容易从Wind那里敲诈来的装备,于是它们想知道在能力范围内,它们最多可以拿多少价值的物品。
你能帮助它们吗?
输入
每组测试数据
第1行为n,Wmax,k(0<=n,Wmax,k<=1000)
接下来n行,为每个物品的Pi,Wi(0<=Pi<=1000,1<=Wi<=10,均为整数)
再接下来k行,每行2个数字a,b表示a和b会发生爆炸
输出
对每组数据输出1行,为最大可能价值
样例输入
3 10 1
100 1
200 5
10 5
1 2
样例输出
210
并查集+背包,最后73分有点小遗憾,我的思路是搞一个结构体,每加入一个物品就把它的f存进去,再加入的话判断一下,CSDN上看到一个不错的思路,同一结构体的存一组,每组只能选一个
我该复习DP和背包了
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#pragma GCC optimize(2)
using namespace std;
int n,wm,k;
int f[1001],t[1001][1001];
int an[1001];
int w[1001],v[1001];
inline int fin(int x)
{
if(f[x]==x)return x;
return f[x]=fin(f[x]);
}
inline void un(int x,int y)
{
int xx=fin(x),yy=fin(y);
if(xx!=yy)
f[xx]=yy;
}
signed main()
{
cin>>n>>wm>>k;
for(int i=1;i<=n;i++)
{
f[i]=i;
cin>>v[i]>>w[i];
}
for(int i=1;i<=k;i++)
{
int x,y;
cin>>x>>y;
un(x,y);
}
for(int i=1;i<=n;i++)
{
int p=fin(i);
t[p][++t[p][0]]=i;
}
for(int i=1;i<=n;i++)
{
if(t[i][0]==0)continue;
for(int j=wm;j>=0;j--)//这里不知道会用到哪一个物品,所以为0
{
for(int l=1;l<=t[i][0];l++)
{
if(j>=w[t[i][l]])
an[j]=max(an[j],an[j-w[t[i][l]]]+v[t[i][l]]);
}
}
}
cout<<an[wm];
return 0;
}
笔记本电池没电了,剩下明天继续补
-------------------------------------------
个性签名:曾经的我们空有一颗望海的心,却从没为前往大海做过真正的努力
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!