Codeforces 786 B. Legacy

题目链接:http://codeforces.com/contest/786/problem/B


  典型线段树优化连边,线段树上的每一个点表示这个区间的所有点,然后边数就被优化为了至多${nlogn}$条,注意要区分$2$,$3$操作(建两棵线段树),然后最短路即可。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 1001000
#define llg long long
#define INC 300000
#define SIZE 2000000
#define inf (llg)1e18
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,dis[maxn],dl[SIZE+],head,tail,pos[maxn];
bool bj[maxn]; vector<llg>a[maxn],val[maxn]; inline int getint()
{
int w=,q=; char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;
} void link(llg x,llg y,llg z) {a[x].push_back(y),val[x].push_back(z);} void build(llg o,llg l,llg r)
{
if (l==r)
{
pos[l]=o;
return ;
}
llg mid=(l+r)>>,lc=o<<,rc=o<<|;
build(lc,l,mid); build(rc,mid+,r);
} void find(llg o,llg l,llg r,llg L,llg R,llg val,bool f,llg v)
{
if (l>=L && r<=R)
{
if (f) link(pos[v],o,val);else link(o+INC,pos[v],val);
return ;
}
llg mid=(l+r)>>,lc=o<<,rc=o<<|;
if (mid>=L) find(lc,l,mid,L,R,val,f,v);
if (mid<R) find(rc,mid+,r,L,R,val,f,v);
} void link_fa(llg o,llg l,llg r)
{
for (llg i=l;i<=r;i++) link(o,pos[i],),link(pos[i],o+INC,);
if (l==r) return ;
llg mid=(l+r)>>,lc=o<<,rc=o<<|;
link_fa(lc,l,mid); link_fa(rc,mid+,r);
} void init()
{
llg t,v,u,w,l,r,s,q;
n=getint(),q=getint(),s=getint();
build(,,n);
for (llg i=;i<=q;i++)
{
t=getint();
if (t==)
{
v=getint(),u=getint(),w=getint();
link(pos[v],pos[u],w);
}
if (t==)
{
v=getint(),l=getint(),r=getint(),w=getint();
find(,,n,l,r,w,,v);
}
if (t==)
{
v=getint(),l=getint(),r=getint(),w=getint();
find(,,n,l,r,w,,v);
}
}
link_fa(,,n);
for (llg i=;i<maxn;i++) dis[i]=inf;
dis[pos[s]]=;
dl[]=pos[s],head=,tail=;
} void spfa()
{
llg w,x,v;
do
{
head%=SIZE; head++;
x=dl[head]; w=a[x].size(); bj[x]=;
for (llg i=;i<w;i++)
{
v=a[x][i];
if (dis[v]>dis[x]+val[x][i])
{
dis[v]=dis[x]+val[x][i];
if (!bj[v])
{
bj[v]=;
tail%=SIZE; tail++;
dl[tail]=v;
}
}
}
}while (head!=tail);
} int main()
{
yyj("graph");
init();
spfa();
for (llg i=;i<=n;i++) if (dis[pos[i]]==inf) printf("-1 "); else printf("%lld ",dis[pos[i]]);
return ;
}
上一篇:【FFMPEG】基于RTP的H264视频数据打包解包类


下一篇:在项目中 background transiton 带来的"便利"与“坑”