CF786B Legacy
线段树优化建图
开一棵儿子向父亲连0边的线段树1
另一棵父亲向儿子连0边的线段树0
0向1的对应节点连0边
对于点向区间加边,我们从1对应的节点向0对应的区间连边
对于区间向点加边,我们从1对应的区间向0对应的节点连边
然后跑手写堆优化Dijkstra即可
时间复杂度\(\Theta ((n+m\log n)\log n)\)
#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;
const int MAXN=1<<17;
int n,m,s,np,siz;
int h[MAXN<<2],hp[MAXN<<2],id[MAXN<<2],rid[MAXN];
long long ln[MAXN<<2];
struct rpg{
int li,nx,ln;
}a[MAXN<<4];
void add(int ls,int nx,int ln){a[++np]=(rpg){h[ls],nx,ln};h[ls]=np;}
void res(int k,int l,int r)
{
siz=max(siz,k);
if(l==r) return;
int i=k<<1,mid=l+r>>1;
res(i,l,mid);res(i|1,mid+1,r);
return;
}
void build(int k,int l,int r)
{
add(k,k+siz,0);
if(l==r){rid[l]=k;return;}
int i=k<<1,mid=l+r>>1;
build(i,l,mid);build(i|1,mid+1,r);
add(k,i,0);add(k,i|1,0);
add(i+siz,k+siz,0);add((i|1)+siz,k+siz,0);
return;
}
void slv1()
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
add(rid[x]+siz,rid[y],z);
return;
}
void cadd(int k,int l,int r,int le,int ri,int ln,int x,bool kd)
{
if(le<=l&&r<=ri){
if(!kd) add(x,k,ln);
else add(k+siz,x,ln);
return;
}int i=k<<1,mid=l+r>>1;
if(le<=mid) cadd(i,l,mid,le,ri,ln,x,kd);
if(mid<ri) cadd(i|1,mid+1,r,le,ri,ln,x,kd);
return;
}
void slv2()
{
int x,y1,y2,z;scanf("%d%d%d%d",&x,&y1,&y2,&z);
cadd(1,1,n,y1,y2,z,rid[x]+siz,0);
return;
}
void slv3()
{
int x1,x2,y,z;scanf("%d%d%d%d",&y,&x1,&x2,&z);
cadd(1,1,n,x1,x2,z,rid[y],1);
return;
}
void up(int x)
{
for(int i=x,j=i>>1;j;i=j,j>>=1){
if(ln[hp[i]]<ln[hp[j]]) swap(hp[i],hp[j]),swap(id[hp[i]],id[hp[j]]);
else break;
}return;
}
void ins(int x)
{
hp[++hp[0]]=x;
id[x]=hp[0];
up(hp[0]);
return;
}
void pop()
{
id[hp[1]]=0;
hp[1]=hp[hp[0]--];
id[hp[1]]=1;
for(int i=1,j=2;j<=hp[0];i=j,j<<=1){
if(j<hp[0]&&ln[hp[j+1]]<ln[hp[j]]) ++j;
if(ln[hp[i]]>ln[hp[j]]) swap(hp[i],hp[j]),swap(id[hp[i]],id[hp[j]]);
else break;
}return;
}
void Dijkstra(int s)
{
memset(ln,0x7f,sizeof(ln));
ln[s]=0;ins(s);
while(hp[0]){
int nw=hp[1];pop();
for(int i=h[nw];i;i=a[i].li){
if(ln[a[i].nx]>ln[nw]+a[i].ln){
ln[a[i].nx]=ln[nw]+a[i].ln;
if(id[a[i].nx]) up(id[a[i].nx]);
else ins(a[i].nx);
}
}
}return;
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
res(1,1,n);
build(1,1,n);
while(m--){
int c;scanf("%d",&c);
if(c==1) slv1();
else if(c==2) slv2();
else slv3();
}Dijkstra(rid[s]);
for(int i=1;i<=n;++i) printf("%lld ",ln[rid[i]]<1e15?ln[rid[i]]:-1ll);
return 0;
}
用先进的科学技术与思想文化武装起来的人民,是一个国家最巨大的生产力,是一个社会最强大的推动力,是一个民族最坚实的自信力,是一支军队最可靠的战斗力。
——A·H