传送门
文章目录
- 题意:
- 思路:
题意:
实现如下连边后跑最短路。
思路:
优化建图板子题,优化思路就是将区间分割成若干个线段树上的线段,与线段树分治有点类似,由于有点向区间也有区间向点的边,那么我们需要建两颗线段树,点向区间的树是自顶向下连边,区间向点的是自底向上连边,最后两棵树的最后一层需要与原来的nnn个点连双向(未经说明都是单向边),比如下面这个图(盗用了日报的图)
让后我们就按照图来建边就好啦,我这里第一颗编号是[1,4∗n][1,4*n][1,4∗n],第二棵编号是[4∗n+1,8∗n][4*n+1,8*n][4∗n+1,8∗n],绿色点是[8∗n+1,9∗n][8*n+1,9*n][8∗n+1,9∗n]。
当然可以舍去绿色的点,直接以线段树叶子节点为绿色的点,下面也给出代码了,只需要记一下leaf[i]leaf[i]leaf[i]即可。
// Problem: B. Legacy
// Contest: Codeforces - Codeforces Round #406 (Div. 1)
// URL: https://codeforces.com/problemset/problem/786/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,int> PII;const int N=900200,M=N*40,mod=1e9+7,INF=0x3f3f3f3f;
const LL inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-6;int n,q,s,b1,b2;
int e[M],ne[M],w[M],h[N],idx;
LL dis[N];
bool st[N];
//第一颗线段树1-4*n 第二棵4*n+1-8*n 点8*n+1-9*nvoid add(int a,int b,int c) {e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}void build(int u,int l,int r) {if(l==r) {add(u,l+8*n,0); add(l+8*n,u,0);add(u+4*n,l+8*n,0); add(l+8*n,u+4*n,0);return;}add(u,u*2,0); add(u,u*2+1,0);add(u*2+4*n,u+4*n,0); add(u*2+1+4*n,u+4*n,0);int mid=(l+r)>>1;build(u<<1,l,mid); build(u<<1|1,mid+1,r);
}void change1(int u,int l,int r,int ql,int qr,int st,int cs) {if(ql<=l&&qr>=r) {add(st+8*n,u,cs);return;}int mid=(l+r)>>1;if(ql<=mid) change1(u<<1,l,mid,ql,qr,st,cs);if(qr>mid) change1(u<<1|1,mid+1,r,ql,qr,st,cs);
}void change2(int u,int l,int r,int ql,int qr,int st,int cs) {if(ql<=l&&qr>=r) {add(u+4*n,st+8*n,cs);return;}int mid=(l+r)>>1;if(ql<=mid) change2(u<<1,l,mid,ql,qr,st,cs);if(qr>mid) change2(u<<1|1,mid+1,r,ql,qr,st,cs);
}void dijkstra() {priority_queue<PII,vector<PII>,greater<PII> >q; q.push({0ll,s+8*n});memset(dis,0x3f3f3f3f,sizeof(dis));dis[s+8*n]=0;while(q.size()) {PII u=q.top(); q.pop();if(st[u.Y]) continue;st[u.Y]=1;for(int i=h[u.Y];~i;i=ne[i]) {int j=e[i];if(dis[j]>dis[u.Y]+w[i]) {dis[j]=dis[u.Y]+w[i];q.push({dis[j],j});}}}for(int i=1;i<=n;i++) printf("%lld ",dis[i+8*n]==inf? -1:dis[i+8*n]);
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);memset(h,-1,sizeof(h));cin>>n>>q>>s;build(1,1,n);while(q--) {int op,v,l,r,c;scanf("%d",&op);if(op==1) {scanf("%d%d%d",&l,&r,&c);add(l+8*n,r+8*n,c);}else if(op==2) {scanf("%d%d%d%d",&v,&l,&r,&c);change1(1,1,n,l,r,v,c);}else {scanf("%d%d%d%d",&v,&l,&r,&c);change2(1,1,n,l,r,v,c);}}dijkstra();return 0;
}
/**/
// Problem: B. Legacy
// Contest: Codeforces - Codeforces Round #406 (Div. 1)
// URL: https://codeforces.com/problemset/problem/786/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,int> PII;const int N=800200,M=N*20,mod=1e9+7,INF=0x3f3f3f3f;
const LL inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-6;int n,q,s,b1,b2;
int e[M],ne[M],w[M],h[N],idx;
int leaf[N];
LL dis[N];
bool st[N];
//第一颗线段树1-4*n 第二棵4*n+1-8*n void add(int a,int b,int c) {e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}void build(int u,int l,int r) {if(l==r) {leaf[l]=u;return;}int mid=(l+r)>>1;add(u,u*2,0); add(u,u*2+1,0);add(u*2+4*n,u+4*n,0); add(u*2+1+4*n,u+4*n,0);build(u<<1,l,mid); build(u<<1|1,mid+1,r);
}void change1(int u,int l,int r,int ql,int qr,int st,int w) {if(ql<=l&&qr>=r) {add(st,u,w);return;}int mid=(l+r)>>1;if(ql<=mid) change1(u<<1,l,mid,ql,qr,st,w);if(qr>mid) change1(u<<1|1,mid+1,r,ql,qr,st,w);
}void change2(int u,int l,int r,int ql,int qr,int st,int w) {if(ql<=l&&qr>=r) {add(u+4*n,st,w);return;}int mid=(l+r)>>1;if(ql<=mid) change2(u<<1,l,mid,ql,qr,st,w);if(qr>mid) change2(u<<1|1,mid+1,r,ql,qr,st,w);
}void dijkstra() {memset(dis,0x3f3f3f3f,sizeof(dis));priority_queue<PII,vector<PII>,greater<PII>>q;q.push({s,leaf[s]}); dis[leaf[s]]=0;while(q.size()) {PII u=q.top(); q.pop();if(st[u.Y]) continue;st[u.Y]=1;for(int i=h[u.Y];~i;i=ne[i]) {int j=e[i];if(dis[j]>dis[u.Y]+w[i]) {dis[j]=dis[u.Y]+w[i];q.push({dis[j],j});}}}for(int i=1;i<=n;i++) printf("%lld ",dis[leaf[i]]==inf? -1:dis[leaf[i]]);
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);memset(h,-1,sizeof(h));cin>>n>>q>>s;build(1,1,n);for(int i=1;i<=n;i++) add(leaf[i],leaf[i]+4*n,0),add(leaf[i]+4*n,leaf[i],0);while(q--) {int op,v,l,r,c;scanf("%d",&op);if(op==1) {scanf("%d%d%d",&l,&r,&c);add(leaf[l],leaf[r],c);}else if(op==2) {scanf("%d%d%d%d",&v,&l,&r,&c);change1(1,1,n,l,r,leaf[v],c);}else {scanf("%d%d%d%d",&v,&l,&r,&c);change2(1,1,n,l,r,leaf[v],c);}}dijkstra();return 0;
}
/**/