目录
1.最高的牛
题目连接:https://www.acwing.com/problem/content/description/103/
题意:现在有n头牛,我们只知道其中的最高牛的高度和位置,现在给了m个关系,每个关系输入a,b.表示牛a和牛b可以互相看见
俩头牛能互相看见的条件是俩头牛之间的牛头比他们矮,求每头牛最大的身高
注意不会出现交叉的情况如下图所示:
思路:首先初始化每头牛的高度为最高牛的高度H,求一个差分数组d,对于每次输入的a,b,我们让[a,b](不包括a,b)之间的牛的身高比俩边的少1就行,这就转为了区间加数的问题,差分就解决了。
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int d[N];
bool vis[N][N];
int main()
{
int n,p,h,m;
cin>>n>>p>>h>>m;
d[1]+=h;
int a,b;
while(m--){
cin>>a>>b;
if(a>b) swap(a,b);
if(!vis[a][b]){
d[a+1]--;
d[b]++;
vis[a][b]=1;
}
}
// for(int i=1;i<=n;i++) cout<<d[i]<<" ";
for(int i=1;i<=n;i++){
d[i]+=d[i-1];
cout<<d[i]<<endl;
}
return 0;
}c
2.蒜头君的数轴
题目连接:https://nanti.jisuanke.com/t/A1633
题意:最多只有一个相邻点的距离和其他的不同,问最少加多少点
思路:有一个距离和其他的不同肯定比所有距离都相同要加的点少,枚举一下[1,n-1]每个距离,剩下的n-2个距离要相同,所以要求一下剩下n-2个距离的最大公约数GCD,直接求会超时,所以需要用一下前缀gcd和后缀gcd,前缀gcd和后缀gcd 在求一下gcd就算出来GCD了,如图
sum:出了枚举的距离外所的距离和 。 sum/GCD:长度为GCD 的距离的段数 现在有n-2段 ,所以需要加的点数为sum/GCD-(n-2). 最后每次更新这个最小值
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int a[N],d[N];
int pre[N],suf[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
ll sum=0;
for(int i=1;i<n;i++){
d[i]=a[i]-a[i-1];//每一段的距离
sum+=d[i];
}
// cout<<sum<<endl;
//预处理前缀gcd和后缀gcd
for(int i=1;i<n;i++) pre[i]=__gcd(d[i],pre[i-1]);
for(int i=n-1;i>=1;i--) suf[i]=__gcd(d[i],suf[i+1]);
ll ans=0x3f3f3f3f;
for(int i=1;i<n;i++){
sum-=d[i];
// cout<<sum<<" "<<__gcd(pre[i-1],suf[i+1])<<endl;
ans=min(ans,sum/(ll)__gcd(pre[i-1],suf[i+1])-(n-2));
sum+=d[i];
}
cout<<ans<<endl;
return 0;
}
3.Covered Points Count
题目连接:
题意:现在有n条线段 求被覆盖k次的点的个数 k∈[1,n]
思路:点的位置比较大10^18,不能用数组来做差分,但是可以用map来做,遍历map,维护一下前缀和sum,然后每次更新一下答案数组即可。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll ans[N];
map<ll,ll> mp;
int main()
{
int n;
cin>>n;
ll l,r;
for(int i=1;i<=n;i++){
cin>>l>>r;
mp[l]++;
mp[r+1]--;
}
map<ll,ll>::iterator it=mp.begin();
ll sum=0;//sum求前缀和
for(it;it!=mp.end();it++){
map<ll,ll>::iterator nex=it;
nex++;
if(nex==mp.end()) break;
sum+=it->second;
// cout<<ans[1]<<endl;
ans[sum]+=nex->first-it->first;
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
return 0;
}