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;
}
posted @ 2025-08-07 16:52  arin876  阅读(12)  评论(0)    收藏  举报