看到区间操作想到用线段树优化建树,建一棵外向树一棵内向树,用线段树点代表整个区间内的所有点。
大佬的图
从树上找节点然后连边就可以,最后跑个dijktra就完成了。
我一次就过样例了,改了几次内存就过了这题,太好了!!!
#include <bits/stdc++.h>
#define ll long long
#define int ll
#define ls p<<1
#define rs p<<1|1
#define re register
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
#define lb(x) x&(-x);
using namespace std;
const int N=1e6+10;
const int M=8e6+10;
const int mod=1e9+7;int n,q,s;
int cnt;
struct sss{int v,w;
};vector<sss> a[N];struct ss{int l,r,id;
}t1[N<<1],t2[N<<1];int top1,top2;int build1(int p,int l,int r){if(l==r){return t1[l].id;}t1[p].id=p;int mid=(l+r)>>1;t1[p].l=build1(++cnt,l,mid);t1[p].r=build1(++cnt,mid+1,r);a[p].push_back({t1[p].l,0});a[p].push_back({t1[p].r,0});return p;
}int build2(int p,int l,int r){if(l==r){return t2[l].id;}t2[p].id=p;int mid=(l+r)>>1;t2[p].l=build2(++cnt,l,mid);t2[p].r=build2(++cnt,mid+1,r);a[t2[p].l].push_back({p,0});a[t2[p].r].push_back({p,0});return p;
}void change1(int p,int pl,int pr,int l,int r,int x,int w){if(pl>=l&&pr<=r){a[x].push_back({p,w});return;}int mid=(pl+pr)>>1;if(l<=mid) change1(t1[p].l,pl,mid,l,r,x,w);if(r>mid) change1(t1[p].r,mid+1,pr,l,r,x,w);
}void change2(int p,int pl,int pr,int l,int r,int x,int w){if(pl>=l&&pr<=r){a[p].push_back({x,w});return;}int mid=(pl+pr)>>1;if(l<=mid) change2(t2[p].l,pl,mid,l,r,x,w);if(r>mid) change2(t2[p].r,mid+1,pr,l,r,x,w);
}
int dis[N];
int vis[N];
void dijkstra(int s){for(int i=1;i<=cnt;i++) dis[i]=1e18;dis[s]=0;priority_queue<pir,vector<pir>,greater<pir> > q;q.push({0,s});while(!q.empty()){int u=q.top().second;q.pop();if(vis[u]) continue;vis[u]=1;for(auto i:a[u]){int v=i.v;int w=i.w;if(dis[v]>dis[u]+w){dis[v]=dis[u]+w;q.push({dis[v],v});}}}
}signed main(){ios::sync_with_stdio(0);cin.tie(nullptr); cin>>n>>q>>s;for(int i=1;i<=n;i++){t1[i].id=i;t2[i].id=i+n;a[i].push_back({i+n,0});a[i+n].push_back({i,0});}cnt=2*n;top1=build1(++cnt,1,n);top2=build2(++cnt,1,n);for(int i=1;i<=q;i++){int op,u,v,w,l,r;cin>>op;if(op==1){cin>>u>>v>>w;a[u].push_back({v,w});}else if(op==2){cin>>u>>l>>r>>w;change1(top1,1,n,l,r,u+n,w);}else{cin>>u>>l>>r>>w;change2(top2,1,n,l,r,u,w);}}dijkstra(s);for(int i=1;i<=n;i++){if(dis[i]==1e18) cout<<"-1 ";else cout<<dis[i]<<" ";}return 0;
}