河南萌新(五)补题

共补9题

bdegji略;

F:dijkstra的变形题,从家到打卡点后又回家,是一个有向环,先算从家到打卡点的最短路,然后将所有有向边反转一下,再求此最短路,想加就是这个环的最短路径;

代码略;

H:区间最大值:

比较典型的题目,可以用树状数组或者st表来做;按理来说两种方法都是o(nlogn),不知道为啥st可以,树状数组会超时

做个树状数组求区间最大值(o(nlogn))代码笔记:(过不了题目,超时了)

#include <bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N=1e6+10;

int n,q,arr[N];
int bitree[N]={0};

int lowbit(int t){
    return t&(-t);
}
void add(int i,int n){//时间复杂度o(logn)
    if(i==0) return;
    while(i<n){
        bitree[i]=max(bitree[i],n);
        i+=lowbit(i);
    }
}

// void update(int i,int k)//时间复杂度o((logn)^2)
// {
//     int lb;
//     bitree[i]=arr[i]=k;//原数组也要跟着改变,求区间最大值要用
//     while(i<=n)
//     {
//         lb=lowbit(i);
//         bitree[i]=arr[i];
//         for(int j=1;j<lb;j<<=1)
//             bitree[i]=max(bitree[i],bitree[i-j]);
//         i+=lowbit(i);
//     }
// }

//递归::

// int query(int x,int y){
//     if(y-lowbit(y)>x) return max(query(x,y-lowbit(y)),bitree[y]);
//     else return max(arr[x],query(x,y-1));
// }

//循环::
int query(int x, int y){
    int ans=0;
    while(x<=y){
        ans=max(ans,arr[y]);
        y--;
        for(;y-lowbit(y)>x;y-=lowbit(y))
            ans=max(ans,bitree[y]);
    }
    return ans;
}

// int query(int lef,int rig)
// {
//     int res=0;
//     while(rig>=lef)
//     {
//         if(rig-lowbit(rig)+1>=lef)
//         {
//             res=max(res,bitree[rig]);
//             rig=rig-lowbit(rig);
//         }
//         else
//         {
//             res=max(res,arr[rig]);
//             --rig;
//         }
//     }
//     return res;
// }
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) {
        scanf("%d",&arr[i]);
        add(i,arr[i]);
    }
    cin>>q;
    while(q--){
        int l,r;
        cin>>l>>r;
        cout<<query(l,r)<<endl;
    }
    
        
return 0;}

st表求静态数组区间最大值::(cin关流可以AC)

#include <bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N=1e6+100;
#define endl '\n'
ll n,q,arr[N];
ll st[N][24]={0};
ll Log2[N]={0};
int query(int l,int r){
    int t =log2(r-l+1);
    return max(st[l][t],st[r-(1<<t)+1][t]);
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) {
        //scanf(" %lld ",&arr[i]);
        cin>>arr[i];
    }
    //预处理st表
    for(int i=1;i<=n;i++){
        st[i][0]=arr[i];
    }
    for(int j=1;j<24;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        }
    }
     //为了方便查询,预处log2表||也可以用
     //Log2[1]=0;
     //for(int i=2;i<=n+1;i++) Log2[i]=Log2[i/2]+1;//向下取整;
    cin>>q;
    while(q--){
        int l,r;
        cin>>l>>r;
        //int t=Log2[r-l+1];
        
        printf("%d\n",query(l,r));
    }
return 0;}

K:经典的最短路径之最大权重的最小值;是dijkstra的变形体(和原本的dij相差较大)dist【N】数组中存的是最短路径中的最大权重;

#include <bits/stdc++.h> 
using namespace std;
#define endl '\n'
#define int long long
#define IOS std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef pair<int,int> PII;
const int N=4e4+10,M=4e4+10;

int h[N],ne[M],e[N],w[M],idx=0;

int n,m;
int s,x;
int dist[N];
bool st[N];

void add(int a,int b,int c){
    e[idx]=b;ne[idx]=h[a];h[a]=idx;w[idx]=c;idx++;
}

int distra(){
    memset(dist,0x3f,sizeof dist);    
    dist[s]=0;//将s节点当做第一个节点
    
    priority_queue <PII,vector<PII>,greater<PII>> heap;
    heap.push({0,s});
    
    while(!heap.empty()){
        PII q=heap.top();
        heap.pop();
        
        int ver=q.second,dis=q.first;
        
        if(st[ver]) continue;
        st[ver]=true;
        
        for(int i=h[ver];i!=-1;i=ne[i]){//这一块是与原版不同的主要地方(重要变化)
            int j=e[i];
            if(dist[j]>max(dist[ver],w[i])){
                dist[j]=max(dist[ver],w[i]);
                heap.push({dist[j],j});
            }
        }
    }
   return dist[x];//x节点当做第n个结点
}

signed main(){
    IOS;
    cin>>n>>m;
    int u,v,a;
    memset(h,-1,sizeof h);
    while(m--){
        cin>>u>>v>>a;
        add(u,v,a);
        add(v,u,a);//无向图
    }
    cin>>s>>x;
    cout<<distra()<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值