A.B略
C-Friends and Travel costs(思维)
思路:题目限定了从i村庄到(i+1)村庄有path,其他村庄之间无path,限定了此道题就是一维坐标轴的情况(直线步行),不是图。你有k元(ans=k,用ans存),而你每从i村庄到(i+1)村庄你就要花费1元,此时你在0村庄,自己想一下,比如,你现在身上有3元,那么你可以从0村庄到3村庄,0->1->2->3,也就是说你身上的钱对应着你能走到第几个村庄(路上没有朋友的情况);但是路上如果有你的朋友的话,你就可以补充身上的钱了。那么:
if(ans>=a[i].first) ans+=a[i].second;
else {
cout<<ans<<endl;
return 0;
}
完整代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
typedef pair<ll,ll> PII;
ll n,k,ans;
PII a[N];
int main()
{
cin>>n>>k;
for (int i=1;i<=n;i++){
ll p,q;
cin>>p>>q;
a[i]={p,q};
}
sort(a+1,a+n+1);
ans=k;
for(int i=1;i<=n;i++){
if(ans>=a[i].first) ans+=a[i].second;
else {
cout<<ans<<endl;
return 0;
}
}
cout<<ans<<endl;
return 0;
}
D-Pond(二维前缀和+二分)
题意:给出一个N * N的矩阵,然后依次枚举k * k的子矩阵,求子矩阵第k*k/2+1大的所有数中的最小值。
思路和完整代码如下:
#include <bits/stdc++.h>
using namespace std;
int a[810][810],s[810][810];
int n,k;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
int l=0,r=1e9,mid,ans=-1;
while(l<=r)
{
mid=(l+r)/2;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
s[i][j]=(a[i][j]<=mid);//小于等于mid的数都置为1
//1.预处理出二维前缀和
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
bool flag=0;
//2.枚举框出的k*k小方块的右下角坐标(i,j),左上角坐标即是(i-k+1,j-k+1).
for(int i=k;i<=n;i++)
for(int j=k;j<=n;j++)
{
//s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k]
//即为以(i-k+1, j-k+1)为左上角,(i, j)为右下角的子矩阵的和
//如果在一个子矩阵中,小于等于mid的值大于等于k*k/2+1个
//那么这个子矩阵就存在一个更小的mid的值,因此需要收缩区间
if ((s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k])*2>=k*k)
flag=1;
}
if(flag) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
}