Hello,大家好!
我是蒟亦先生!
温馨提示:请各位奆奆们洁身自好,请勿COPY!
题解:
浇花
代码实现+解析
首先,我们对题目做一个分析:
前面的一堆废话
关键句:“浇完m次花以后,最矮的花的最大高度。”——这很明显是二分的标志。
我们二分最矮的花的高度,然后用O(n)的时间复杂度检查是否可行。
只要浇花的区间固定了,那么顺序对答案没有影响。
因此,从第1株到第n株扫描一遍,每次发现一株高度低于mid的花,就以这株花为区间的左端点,设这株花再长y厘米可以达到mid,就把以这株花为左端点的区间内的所有花高度加上y。
可是,每次浇花时把整个区间遍历一遍,时间复杂度还是有点高。
于是,我们就要用到一个差分的思想。
我们先设差分数组为num,
如果区间[l,r]的值要全部加上y,则num[l]+=y,num[r+1]-=y.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=1e5+5;
ll n,m,w,sum,ans,i,j,h[N],num[N*2];
bool check(ll mid)
{
ll i=1,j,cnt=0,x=m,y;
memset(num,0,sizeof(num));
while(i<=n)
{
while(h[i]+cnt>=mid&&i<=n)
{
cnt-=num[++i];
}
if(i>n)
{
return 1;
}
y=mid-h[i]-cnt;
if(y>x)
{
return 0;
}
num[i+w]=y;
cnt+=y;
x-=y;
cnt-=num[++i];
}
return 1;
}
int main()
{
ll l=9e9,r=-1,mid;
cin>>n>>m>>w;
for(i=1;i<=n;i++)
{
cin>>h[i];
l=min(l,h[i]);
r=max(r,h[i]);
}
r+=m;
while(l<=r)//二分答案
{
mid=(l+r)/2;
if(check(mid))//判断高度低于mid的花
{
l=mid+1;
ans=mid;
}
else
{
r=mid-1;
}
}
cout<<ans;
return 0;
}
读书
代码实现+解析
根据题意,我们可以考虑第i次拿书,那么前面的i-1次拿的书一定都会产生贡献。
换句话说,这里的贡献我们是改变不了的,它是个定值,所以我们只能最小化初始序列对操作所产生的贡献。
因此,初始序列就是每本书第一次被拿出来的顺序。
最后得到初始序列直接模拟就做好了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=1e4;
ll n,m,i,j,cnt,w[N],a[N],b[N*2],bj[N];
int main()
{
cin>>n>>m;
ll cnt=m,l=m+1,ans=0;
for(i=1;i<=n;i++)
{
cin>>w[i];
}
for(i=1;i<=m;i++)
{
cin>>a[i];
}
for(i=1;i<=m;i++)
{
if(bj[a[i]])
{
continue;
}
b[++cnt]=a[i];
bj[a[i]]=1;
}
for(i=1;i<=m;i++)
{
j=l;
while(a[i]!=b[j])
{
ans+=w[b[j++]];
}
b[--l]=a[i];
b[j]=0;
}
cout<<ans;
return 0;
}
奶牛野餐
代码实现+解析
So easy!
大家根据题目应该都能想到思路——
先从每个奶牛所在的地方开始访问,每个节点若能访问到,则对应的次数+1,如果节点次数=奶牛数,则符合题目要求,ans++,最后输出ans即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=1e4+5;
ll lk[maxn],ans,ltp,t1[maxn],f[maxn],h[maxn];//f数组记录节点状态,h数组每次处理f数组的结果
struct zjy
{
ll y,nxt;
}e[maxn];
struct edge//输入时存边
{
ll x,y;
}a[maxn];
void add(ll x,ll y)
{
e[++ltp]={y,lk[x]};
lk[x]=ltp;
}
void dfs(ll x)
{
if(!f[x])
{
f[x]=1;
for(ll i=lk[x];i>=1;i=e[i].nxt)
{
dfs(e[i].y);
}
}
}
int main()
{
ll i,j,k,n,m;
cin>>k>>n>>m;
for(i=1;i<=k;i++)
{
cin>>t1[i];
}
for(i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].y;
}
for(i=1;i<=m;i++)
{
add(a[i].x,a[i].y);
}
for(i=1;i<=k;i++)
{
if(t1[i])
{
dfs(t1[i]);
for(j=1;j<=n;j++)
{
if(f[j])
{
h[j]++;
}
}
memset(f,0,sizeof(f));
}
}
for(i=1;i<=1005;i++)
{
if(h[i]==k)
{
ans++;
}
}
cout<<ans;
return 0;
}
谢谢各位奆奆!
题解制作不易,望能用心思考
如有疑问,欢迎提出问题一起讨论!