[USACO21DEC] Tickets P 题解
[USACO21DEC] Tickets P
首先我们思考暴力的
为什么呢?假如说
如何解决?方法是将
37pts 就有了。
怎么优化到 100pts?线段树优化建图即可。
#include<bits/stdc++.h>
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
#define INF 0x3f3f3f3f3f3f3f3fll
using namespace std;
char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
int read(){
int x=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x;
}
template<typename T>
void write(T x,char sf='\n'){
if(x<0)putchar('-'),x=~x+1;
int top=0;
do str[top++]=x%10,x/=10;while(x);
while(top)putchar(str[--top]+48);
if(sf^'#')putchar(sf);
}
using ll=long long;
using pli=pair<ll,int>;
constexpr int MAXN=4e5+5;
int n,k,tn;
struct Tik{
int c,p,a,b;
}t[MAXN];
int head[MAXN],tot;
struct{
int v,to,w;
}e[5000005];
void addedge(int u,int v,int w){
e[++tot]={v,head[u],w};
head[u]=tot;
}
ll dis[MAXN],d[MAXN];
bool vis[MAXN];
priority_queue<pli>q;
void dijkstra(int s,bool sh=0){
memset(vis,0,sizeof(bool)*(tn+k+5));
if(!sh){
memset(dis,0x3f,sizeof(ll)*(tn+k+5));
dis[s]=0;
q.emplace(0,s);
}else{
memcpy(dis,d,sizeof(ll)*(tn+k+5));
for(int i=1;i<=tn+k;++i)
q.emplace(-dis[i],i);
}
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=e[i].to)
if(dis[e[i].v]>dis[u]+e[i].w){
dis[e[i].v]=dis[u]+e[i].w;
q.emplace(-dis[e[i].v],e[i].v);
}
}
}
#define lp p<<1
#define rp p<<1|1
struct{
struct SegTree{
int l,r,ls,rs;
}st[MAXN];
int build(int s,int t){
if(s==t) return st[s]={s,t,0,0},s;
int mid=(s+t)>>1,x=++tn;
st[x]={s,t,build(s,mid),build(mid+1,t)};
addedge(st[x].ls,x,0);
addedge(st[x].rs,x,0);
return x;
}
void update(int l,int r,int x,int p){
if(l<=st[p].l&&st[p].r<=r) return addedge(p,x,0);
int mid=(st[p].l+st[p].r)>>1;
if(l<=mid) update(l,r,x,st[p].ls);
if(mid<r) update(l,r,x,st[p].rs);
}
}T;
int main(){
n=tn=read(),k=read();
int rt=T.build(1,n);
for(int i=1;i<=k;++i){
t[i]={read(),read(),read(),read()};
addedge(tn+i,t[i].c,t[i].p);
T.update(t[i].a,t[i].b,tn+i,rt);
}
dijkstra(1);
memcpy(d,dis,sizeof(ll)*(tn+k+5));
dijkstra(n);
for(int i=1;i<=tn+k;++i) d[i]+=dis[i];
dijkstra(1,1);
for(int i=1;i<=n;++i) write(d[i]>=INF?-1:dis[i]);
return fw,0;
}
即得易见平凡,仿照上例显然。留作习题答案略,读者自证不难。
反之亦然同理,推论自然成立。略去过程 ,由上可知证毕。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现