2023百度之星程序设计大赛初赛第一场
第五维度
枚举ban掉的人,可以二分得到此时人们理解第五维度的时间
ans选最久的时间即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
const int N=100010;
int n,m,sum;
pair<int,int> node[N];
int pre1[N];int pre2[N];
bool check(int mid,int x){
int t=upper_bound(node+1,node+n+1,make_pair(mid,0ll))-node;//[t,n]开始时间>当前时间mid
int tem=pre1[t-1]*mid-pre2[t-1];
if(node[x].first<=mid){
tem-=node[x].second*(mid-node[x].first);
}
// cout<<"check"<<x<<" "<<mid<<" "<<tem<<endl;
return tem>=m;
}
signed main( )
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>node[i].first>>node[i].second;
}sort(node+1,node+n+1);
sum=0;
for(int i=1;i<=n;i++){
pre1[i]=pre1[i-1]+node[i].second;
pre2[i]=pre2[i-1]+node[i].first*node[i].second;
sum+=node[i].first*node[i].second;
}
int ans=0;
for(int i=1;i<=n;i++){
int l=0;int r=1ll*(2e9+2e9+10);
while(l<r){
int mid=(l+r)>>1;
if(check(mid,i))r=mid;
else l=mid+1;
}
//cout<<"get"<<l<<endl;
ans=max(ans,l);
}
if(ans>1ll*(2e9+2e9+5))cout<<-1;
else
cout<<ans;
return 0;
}
T1公园
bfs跑一遍A到所有点的最短路
bfs跑一遍B到所有点的最短路
bfs跑一遍终点到所有点的最短路
两者必然相遇,至少在n相遇,相遇之后必然一起走,因为A之后走的总路程x,B之后走的总路程y,这个点到终点的最短路z
TEx+FEy>=(TE+FE)z>=(TE+FE-S)z
枚举这个相遇点,A走到这个点+B走到这个点+之后一起走的代价即可
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=40010;
ll TE,FE,S;
ll T,F,n,m;
vector<ll> G[N];
ll d1[N],d2[N],d3[N];
int main( )
{
std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>TE>>FE>>S;
cin>>T>>F>>n>>m;
while(m--){
ll u,v;
cin>>u>>v;
G[u].push_back(v);G[v].push_back(u);
}
for(ll i=1;i<=n;i++){d1[i]=d2[i]=d3[i]=-1;}
queue<ll> q;
q.push(T);d1[T]=0;
while(!q.empty()){
ll t=q.front();q.pop();
for(auto v:G[t]){
if(d1[v]==-1){
d1[v]=d1[t]+1;q.push(v);
}
}
}
q.push(F);d2[F]=0;
while(!q.empty()){
ll t=q.front();q.pop();
for(auto v:G[t]){
if(d2[v]==-1){
d2[v]=d2[t]+1;q.push(v);
}
}
}
q.push(n);d3[n]=0;
while(!q.empty()){
ll t=q.front();q.pop();
for(auto v:G[t]){
if(d3[v]==-1){
d3[v]=d3[t]+1;q.push(v);
}
}
}
ll ans=-1;
for(ll i=1;i<=n;i++){
if(d1[i]==-1||d2[i]==-1||d3[i]==-1)continue;
ll tem=TE*d1[i]+FE*d2[i]+(TE+FE-S)*d3[i];
if(ans==-1)ans=tem;
else ans=min(ans,tem);
}
cout<<ans;
return 0;
}
T2蛋糕划分
调死我了
二分,枚举列切割的状态,如果这列后面有切,置1
再看行,如果这块>=mid,就要在这行前面切割,重新计算
最后如果切割次数<=k就可以
#include<bits/stdc++.h>
#define int long long
using namespace std;
/*
2 1
8 7
9 10
*///17
const int N=20;
int n,k;
int mx=0;
int a[N][N];
int s[N][N];
bool check(int mid){
if(mx>mid)return 0;
for(int sta=1;sta<(1ll<<(n+1));sta++){
if(sta&(1ll<<n));else continue;
vector<int> vec;
for(int j=1;j<=n;j++){if(sta&(1ll<<j))vec.push_back(j);}
int cnt=0;bool c=0;
int sti=1;
for(int i=1;i<=n;i++){
bool f=0;int stj=1;
for(auto j:vec){//一块
int x1=sti;int x2=i;int y1=stj;int y2=j;
int tem=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
if(tem>mid){f=1;break;}
stj=j+1;
}
if(f&&i==sti){
c=1;
break;
}
if(f){
sti=i;cnt++;//行切
i=sti-1;
}
}
if(c){
continue;
}
int chk=cnt+vec.size();if(vec.size()&&vec.back()==n)chk--;
if(chk<=k) return 1;
}
return 0;
}
signed main( )
{
std::ios::sync_with_stdio(false);//cin.tie(0);cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){cin>>a[i][j];mx=max(mx,a[i][j]);}
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]+a[i][j];
}
int l=0;int r=1000*n*n;
while(l<r){
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}

浙公网安备 33010602011771号