Legacy

本文解析了CodeForces平台上B题“Legacy”的算法思路,采用线段树优化建图和堆优化迪杰斯特拉算法解决跨星球旅行问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://codeforces.com/problemset/problem/786/B
B. Legacy
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.

There are n planets in their universe numbered from 1 to n. Rick is in planet number s (the earth) and he doesn’t know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he’s still using its free trial.

By default he can not open any portal by this gun. There are q plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.

Plans on the website have three types:

With a plan of this type you can open a portal from planet v to planet u.
With a plan of this type you can open a portal from planet v to any planet with index in range [l, r].
With a plan of this type you can open a portal from any planet with index in range [l, r] to planet v. 

Rick doesn’t known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.
Input

The first line of input contains three integers n, q and s (1 ≤ n, q ≤ 105, 1 ≤ s ≤ n) — number of planets, number of plans and index of earth respectively.

The next q lines contain the plans. Each line starts with a number t, type of that plan (1 ≤ t ≤ 3). If t = 1 then it is followed by three integers v, u and w where w is the cost of that plan (1 ≤ v, u ≤ n, 1 ≤ w ≤ 109). Otherwise it is followed by four integers v, l, r and w where w is the cost of that plan (1 ≤ v ≤ n, 1 ≤ l ≤ r ≤ n, 1 ≤ w ≤ 109).
Output

In the first and only line of output print n integers separated by spaces. i-th of them should be minimum money to get from earth to i-th planet, or  - 1 if it’s impossible to get to that planet.
Examples
Input
Copy

3 5 1
2 3 2 3 17
2 3 2 2 16
2 2 2 3 3
3 3 1 1 12
1 3 3 17

Output

0 28 12

Input
Copy

4 3 1
3 4 1 3 12
2 2 3 4 10
1 2 4 16

Output

0 -1 -1 12

Note

In the first sample testcase, Rick can purchase 4th plan once and then 2nd plan in order to get to get to planet number 2.

题解

线段树优化建图+堆优化dj

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#define ROOT 1,1,n
#define LSON root<<1,l,mid
#define RSON root<<1|1,mid+1,r
using namespace std;
typedef long long ll;
const int maxn=5000000+5;
struct node
{
    int x; ll w;
    bool operator <(const node &o)const
    {
        return w>o.w;
    }
};
priority_queue <node> p;
bool used[maxn];
vector<node> v[maxn];
void add1(int i,int j,int w)
{
    v[i].push_back((node){j,w});
}
int n,m,s,max1;
void build1(int root,int l,int r)
{
    max1=max(max1,root);
    if(l==r)
    {
        add1(root+n,l,0); return;
    }
    int mid=(l+r)>>1;
    build1(LSON); build1(RSON);
    add1(root+n,(root<<1)+n,0); add1(root+n,(root<<1|1)+n,0);
}
void build2(int root,int l,int r)
{
    if(l==r)
    {
        add1(l,root+n+max1,0); return;
    }
    int mid=(l+r)>>1;
    build2(LSON); build2(RSON);
    add1((root<<1)+n+max1,root+n+max1,0); add1((root<<1|1)+n+max1,root+n+max1,0);
}
void modify1(int root,int l,int r,int L,int R,int k,int w)
{
    if(L<=l && r<=R)
    {
        add1(k,root+n,w); return;
    }
    int mid=(l+r)>>1;
    if(R<=mid) modify1(LSON,L,R,k,w);
    else if(L>mid) modify1(RSON,L,R,k,w);
    else modify1(LSON,L,R,k,w),modify1(RSON,L,R,k,w);
}
void modify2(int root,int l,int r,int L,int R,int k,int w)
{
    if(L<=l && r<=R)
    {
        add1(root+n+max1,k,w); return;
    }
    int mid=(l+r)>>1;
    if(R<=mid) modify2(LSON,L,R,k,w);
    else if(L>mid) modify2(RSON,L,R,k,w);
    else modify2(LSON,L,R,k,w),modify2(RSON,L,R,k,w);
}
ll dis[maxn],inf;
int main()
{
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    scanf("%d %d %d",&n,&m,&s);
    build1(ROOT); build2(ROOT);
    for(int i=1; i<=m; i++)
    {
        int opt; scanf("%d",&opt);
        if(opt==1)
        {
            int x,y,w; scanf("%d %d %d",&x,&y,&w);
            if(x!=y) add1(x,y,w);
        }
        else if(opt==2)
        {
            int l,r,x,w; scanf("%d %d %d %d",&x,&l,&r,&w);
            modify1(ROOT,l,r,x,w);
        }
        else
        {
            int l,r,x,w; scanf("%d %d %d %d",&x,&l,&r,&w);
            modify2(ROOT,l,r,x,w);
        }
    }
    memset(dis,62,sizeof(dis));
    inf=dis[0];
    dis[s]=0;
    p.push((node){s,0});
    while(!p.empty())
    {
        node c=p.top(); p.pop();
        if(used[c.x]) continue;
        else
        {
            used[c.x]=true;
            if(!v[c.x].empty())
            {
                for(int i=0; i<v[c.x].size(); i++)
                {
                    node now=v[c.x][i];
                    if(dis[now.x]>dis[c.x]+now.w)
                    {
                        dis[now.x]=dis[c.x]+now.w;
                        p.push((node){now.x,dis[now.x]});
                    }
                }
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        if(dis[i]!=inf)
        {
            printf("%I64d ",dis[i]);
        }
        else
        {
            printf("-1 ");
        }
    }
    return 0;
}
<think>嗯,用户想了解Legacy中断的相关概念和处理方式,以及可能的问题解决。首先,我需要回忆Legacy中断的基础知识。Legacy中断通常指的是传统的基于引脚的中断机制,比如PCI中的INTA-INTD。这和现代的MSI/MSI-X中断不同,后者是基于消息的,不需要物理线路。 接下来,要明确Legacy中断的定义。可能需要参考用户提供的引用内容,特别是引用[3]提到的PCIE XDMA IP核的Legacy Interrupts配置。这里提到需要关闭MSI/MSI-X,勾选INTA等,说明Legacy中断依赖于物理引脚信号,如usr_irq_req和usr_irq_ack。需要解释这些信号的作用,比如请求和应答的流程。 然后,处理方式方面,用户可能想知道Legacy中断的处理流程是怎样的。根据引用[1]和[2],层级中断控制器和链式控制器的处理流程可能不同。比如,链式控制器需要逐级处理中断,而层级可能直接对应GIC中的中断号。Legacy中断可能涉及到中断控制器的链式处理,需要依次读取各个控制器的状态。 另外,引用[2]提到handle_simple_irq会调用注册的中断处理函数,这可能涉及到Legacy中断处理函数的注册过程,比如request_irq()的使用。需要说明驱动程序中如何注册Legacy中断的处理函数,以及应答信号的来源,如引用[3]中提到的应答信号由xdma产生,避免误解。 可能的问题方面,用户可能遇到中断共享的问题,比如多个设备使用同一个中断线,需要驱动支持。还有中断延迟,由于Legacy中断需要物理信号,可能不如MSI/MSI-X高效。此外,配置错误可能导致中断无法触发,比如未正确关闭MSI/MSI-X,或者中断线连接错误。 需要结合用户提供的引用内容,特别是引用[3]中的实验经验,强调应答信号的处理和配置步骤的正确性。同时,对比Legacy中断和MSI/MSI-X的优缺点,帮助用户理解为何在某些情况下仍需使用Legacy中断,比如兼容旧设备。 最后,生成相关问题时,要考虑用户可能的后续疑问,比如如何调试Legacy中断问题,如何优化性能,或者具体的配置案例。需要确保问题覆盖Legacy中断的不同方面,帮助用户深入学习和解决问题。</think>### Legacy中断的定义与处理方式解析 #### 一、Legacy中断定义 Legacy中断(传统中断)是早期计算机系统中基于**物理中断引脚**实现的中断机制,例如PCI/PCIE设备使用的INTA/INTB/INTC/INTD信号。与MSI/MSI-X(Message Signaled Interrupts)不同,Legacy中断需要通过硬件线路传递中断信号,并通过**中断控制器(如8259 PIC或GIC)**进行管理[^3]。 核心特征: 1. **物理线路依赖**:每个中断源需要独占或共享硬件中断线 2. **边沿/电平触发**:通过电压变化检测中断信号 3. **中断共享**:允许多个设备共用同一中断线(需驱动支持) #### 二、Legacy中断处理流程 以PCIE XDMA IP核为例(引用[3]): ``` 1. 硬件触发:设备通过usr_irq_req信号发出中断请求 2. 中断响应:xdma控制器自动生成usr_irq_ack应答信号 3. 中断分发:通过中断控制器(如GIC)路由到CPU 4. 处理函数:调用request_irq()注册的handler函数[^2] ``` 关键寄存器操作: - **关闭MSI/MSI-X**:确保使用传统中断模式 - **配置INTA引脚**:绑定设备到特定中断线 - **状态寄存器检查**:确认中断来源(在链式中断控制器中需逐级查询[^1]) #### 三、常见问题与解决方法 1. **中断丢失问题** - 检查中断应答时序:确保usr_irq_ack信号在1-3个时钟周期内响应[^3] - 验证中断屏蔽寄存器:避免意外屏蔽中断源 2. **中断共享冲突** ```c // 驱动中需实现中断共享支持 request_irq(irq_num, handler, IRQF_SHARED, "dev_name", dev_id); ``` 3. **性能优化** - 对比MSI中断:Legacy中断延迟通常在微秒级,而MSI可达到纳秒级 - 避免长耗时操作:中断处理函数中应使用tasklet或workqueue #### 四、应用场景 1. 兼容旧设备(如传统PCI卡) 2. 低复杂度系统(无需高级中断管理) 3. 特殊硬件限制(如不支持MSI的嵌入式设备)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值