题意
有n个点,q个询问,每次询问有一种操作。操作1:u→[l,r](即u到l,l+1,l+2,...,r距离均为w)的距离为w;操作2:[l,r]→u的距离为w;操作3:u到v的距离为w;求起点到其他点的最短距离,到达不了输出-1。
题解
线段树骚操作,线段树优化建图。
其实提到可以这么操作后,实现还是很好想的。
建两颗线段树,一颗连进边,一颗连出边。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<vector> 9 using namespace std; 10 typedef long long ll; 11 const int MAXN=5e6+100,inf=0x3f3f3f3f,MOD=1e9+7; 12 const ll INF=1e17+10; 13 struct node 14 { 15 int to; 16 ll w; 17 int next; 18 } edge[MAXN]; 19 int cou,head[MAXN]; 20 int Max; 21 int vis[MAXN]; 22 ll ans[MAXN]; 23 void init() 24 { 25 cou=0; 26 Max=0; 27 memset(vis,0,sizeof(vis)); 28 memset(head,-1,sizeof(head)); 29 } 30 void add(int u,int v,ll w) 31 { 32 cou++; 33 edge[cou].to=v; 34 edge[cou].w=w; 35 edge[cou].next=head[u]; 36 head[u]=cou; 37 ///cout<<u<<" "<<v<<" "<<w<<endl; 38 } 39 void build(int l,int r,int pos,int flag,int t) 40 { 41 if(t==2) Max=max(Max,pos+flag); 42 if(l==r) 43 { 44 if(t==2) add(pos+flag,l,0LL); 45 else add(l,pos+flag,0LL); 46 return; 47 } 48 if(t==2) 49 { 50 add(pos+flag,(pos<<1)+flag,0LL); 51 add(pos+flag,(pos<<1|1)+flag,0LL); 52 } 53 else 54 { 55 add((pos<<1)+flag,pos+flag,0LL); 56 add((pos<<1|1)+flag,pos+flag,0LL); 57 } 58 int mid=(l+r)>>1; 59 build(l,mid,pos<<1,flag,t); 60 build(mid+1,r,pos<<1|1,flag,t); 61 } 62 void update(int L,int R,ll w,int l,int r,int pos,int flag,int u,int t) 63 { 64 if(L<=l&&r<=R) 65 { 66 if(t==2) add(u,pos+flag,w); 67 else add(pos+flag,u,w); 68 return; 69 } 70 int mid=(l+r)>>1; 71 if(L<=mid) update(L,R,w,l,mid,pos<<1,flag,u,t); 72 if(R>mid) update(L,R,w,mid+1,r,pos<<1|1,flag,u,t); 73 } 74 struct mmp 75 { 76 int s; 77 ll dis; 78 mmp() {} 79 mmp(ll ss,ll d) 80 { 81 s=ss,dis=d; 82 } 83 bool operator <(const mmp &x)const 84 { 85 return dis>x.dis; 86 } 87 }; 88 priority_queue<mmp>q; 89 void dij(int s) 90 { 91 ans[s]=0LL; 92 q.push(mmp(s,0LL)); 93 while(!q.empty()) 94 { 95 mmp now=q.top(); 96 q.pop(); 97 int u=now.s; 98 if(vis[u]) continue; 99 vis[u]=1; 100 for(int i = head[u]; i!=-1; i=edge[i].next) 101 { 102 int v=edge[i].to; 103 ll w=edge[i].w; 104 if(ans[v]>now.dis+w) 105 { 106 ///cout<<u<<" "<<v<<" "<<ans[u]+w<<endl; 107 q.push(mmp(v,now.dis+w)); 108 ans[v]=now.dis+w; 109 } 110 } 111 } 112 } 113 int main() 114 { 115 int n,q,s; 116 scanf("%d%d%d",&n,&q,&s); 117 init(); 118 build(1,n,1,n+1,2); 119 build(1,n,1,Max+1,3); 120 for(int i=1; i<=q; i++) 121 { 122 int t; 123 scanf("%d",&t); 124 if(t==1) 125 { 126 int u,v; 127 ll w; 128 scanf("%d%d%lld",&u,&v,&w); 129 add(u,v,w); 130 } 131 else 132 { 133 int u,l,r; 134 ll w; 135 scanf("%d%d%d%lld",&u,&l,&r,&w); 136 if(t==2) update(l,r,w,1,n,1,n+1,u,t); 137 else update(l,r,w,1,n,1,Max+1,u,t); 138 } 139 } 140 for(int i=0;i<MAXN;i++) ans[i]=INF; 141 dij(s); 142 for(int i=1; i<=n; i++) 143 { 144 if(ans[i]>=INF) cout<<"-1 "; 145 else cout<<ans[i]<<" "; 146 } 147 cout<<endl; 148 return 0; 149 }
原文地址:https://www.cnblogs.com/Xu-daxia/p/9392987.html
时间: 2024-10-08 06:38:02