51 node 区间交 优先队列(min(r),max(l))

/**
链接:http://www.51nod.com/contest/Problem.html#!problemId=1672&contestId=58
题意 : k个区间共同交的最大数对应的和;
分析:窝们需要找到最满足条件的k个区间 进行不断更新取最大值;
首先由于原序列是递增的,因此维护一个优先队列,只需要将r小的放在前面即可;
由于优先队列已经存在了k个 因此窝们每次放进的当前node.l 都是最大的  但是优先队列维护的是最小的右端点;
因此对于这K个区间来说 node.r和a[i].l 就是需要找的最小的右端点和最大的左端点
************************tricsk******************
ll ans = 1e-18 WA    ...... hehe 
*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=4e5+7;
struct node{
    int l,r;
    friend operator <(node a,node b){
        return a.r>b.r;
    }
}a[maxn];

bool cmp(node a,node b){ return a.l<b.l||(a.l==b.l&&a.r<b.r);}

ll sum[maxn];

priority_queue<node>Q;

int main(){
    int n,k,m,x;scanf("%d %d %d",&n,&k,&m);
    sum[0]=0;
    for(int i=1;i<=n;i++) scanf("%d",&x),sum[i]=sum[i-1]+x;
    for(int i=1;i<=m;i++) scanf("%d %d",&a[i].l,&a[i].r);
    sort(a+1,a+m+1,cmp);
    ll ans=0;
    for(int i=1;i<=m;i++){
        Q.push(a[i]);
        int SZ=Q.size();
        if(Q.size()>k) Q.pop(),SZ--;
        if(Q.size()==k) ans=max(sum[Q.top().r]-sum[a[i].l-1],ans);
    }
    printf("%lld\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言实现优先队列解决旅行售货员问题的代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> // 定义节点信息 typedef struct node { int id; // 节点编号 int dist; // 距离起点的距离 int visited; // 节点是否被访问过 } Node; // 定义优先队列结构体 typedef struct priority_queue { Node* heap; // 存储节点的堆结构 int size; // 堆的大小 int max_size; // 堆的最大大小 } PriorityQueue; // 初始化优先队列 PriorityQueue* init_priority_queue(int max_size) { PriorityQueue* queue = (PriorityQueue*)malloc(sizeof(PriorityQueue)); queue->heap = (Node*)malloc(sizeof(Node) * (max_size+1)); queue->size = 0; queue->max_size = max_size; return queue; } // 将节点插入优先队列 void insert_node(PriorityQueue* queue, Node node) { int i; if (queue->size >= queue->max_size) { // 队列已满 return; } i = ++queue->size; while ((i > 1) && (queue->heap[i/2].dist > node.dist)) { // 上滤操作 queue->heap[i] = queue->heap[i/2]; i /= 2; } queue->heap[i] = node; } // 弹出距离起点最近的节点 Node pop_node(PriorityQueue* queue) { int parent=1, child=2; Node min_node, last_node; if (queue->size == 0) { // 队列为空 return (Node){-1, -1, -1}; } min_node = queue->heap[1]; last_node = queue->heap[queue->size--]; while (child <= queue->size) { // 下滤操作 if ((child < queue->size) && (queue->heap[child].dist > queue->heap[child+1].dist)) { child++; } if (last_node.dist > queue->heap[child].dist) { queue->heap[parent] = queue->heap[child]; } else { break; } parent = child; child *= 2; } queue->heap[parent] = last_node; return min_node; } // 计算旅行售货员问题的近似解 void tsp(PriorityQueue* queue, int** graph, int n) { int i, j; Node node, next_node; int dist[n+1], path[n+1]; for (i = 1; i <= n; i++) { dist[i] = INT_MAX; path[i] = -1; } dist[1] = 0; node.id = 1; node.dist = 0; node.visited = 0; insert_node(queue, node); while (queue->size > 0) { node = pop_node(queue); if (node.visited) { continue; } node.visited = 1; for (j = 1; j <= n; j++) { if ((graph[node.id][j] > 0) && (!queue->heap[j].visited)) { next_node.id = j; next_node.dist = node.dist + graph[node.id][j]; if (next_node.dist < dist[j]) { dist[j] = next_node.dist; path[j] = node.id; insert_node(queue, next_node); } } } } printf("起点:1\n终点:1\n路径:1"); i = path[1]; j = 2; while (i != 1) { printf("-%d", i); i = path[i]; j++; } printf("-1\n路径长度:%d\n", dist[1]); } int main() { int n, i, j; int** graph; PriorityQueue* queue; printf("请输入节点数:\n"); scanf("%d", &n); graph = (int**)malloc(sizeof(int*) * (n+1)); for (i = 1; i <= n; i++) { graph[i] = (int*)malloc(sizeof(int) * (n+1)); for (j = 1; j <= n; j++) { printf("请输入%d到%d的距离:\n", i, j); scanf("%d", &graph[i][j]); } } queue = init_priority_queue(n); tsp(queue, graph, n); return 0; } ``` 该代码使用优先队列来实现近似算法,使用了堆结构来存储节点信息,同时使用了邻接矩阵来存储节点间的距离信息。在计算过程中,使用了Dijkstra算法来计算距离起点最近的节点,并更新与该节点相邻的节点的距离信息。最终输出起点、终点、路径和路径长度等信息。需要注意的是,由于旅行售货员问题是NP难问题,因此使用优先队列解决只能得到近似解,而不能保证得到最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值