CF786B Legacy(线段树优化建图)

题意

有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

CF786B Legacy(线段树优化建图)的相关文章

Codeforces 787D. Legacy 线段树优化建图+最短路

output standard output Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them. There are n planets in their universe numbered from 1 to n.

CF786B Legacy 线段树优化建图

问题描述 CF786B LG-CF786B 题解 线段树优化建图 线段树的一个区间结点代表 \([l,r]\) 区间点. 然后建立区间点的时候就在线段树上建边,有效减少点的个数,从而提高时空效率. 优质题解传送门 \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; #define int long long template <typename Tp> void read(Tp &x){ x=0;ch

【bzoj4276】[ONTAK2015]Bajtman i Okr?g?y Robin 线段树优化建图+费用流

题目描述 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢走c[i]元.作为保安,你在每一段长度为1的时间内最多只能制止一个强盗,那么你最多可以挽回多少损失呢? 输入 第一行包含一个正整数n(1<=n<=5000),表示强盗的个数. 接下来n行,每行包含三个正整数a[i],b[i],c[i](1<=a[i]<b[i]<=5000,1<=c[i]

【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路.Seter保证不会有一个国家与自己之间有道路. Seter好不容易建好了所有道路,他现在在位于P号的首都.Seter想知道P号国家到任意一个国家最少需要经过几条道路.当然,Se

【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一天,她准备去探访他.对着窗外的阳光,临行前她再次弹起了琴.她的琴的发声十分特殊.让我们给一个形式化的定义吧.所有的 n 个音符形成一棵由音符 C ( 1 号节点) 构成的有根树,每一个音符有一个音高 Hi .Arietta 有 m 个力度,第 i 个力度能弹出 Di 节点的子树中,音高在 [Li,R

【ARC069F】Flags 2-sat+线段树优化建图+二分

Description ? 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input ? 第一行一个整数 N. ? 接下来 N 行每行两个整数 xi,yi Output ? 一个整数表示答案. Sample Input Sample #1 3 1 3 2 5 1 9 Sample #2 5 2 2 2 2 2 2 2 2 2 2 Sample #3 22 93 6440 78 6647 862 11 8306 9689 798 99 801 52

一个神秘的oj2587 你猜是不是dp(线段树优化建图)

哇 这难道不是happiness的翻版题嘛? 从\(S\)向一个点连染成白色的收益 从这个点向\(T\)连染成黑色的收益 对于额外的收益,建一个辅助点,跟区间内的每个点连\(inf\),然后向S/T,连流量为收益 这不就结束了吗? 自信写完,提交 woc!!只有40分? #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath>

机房测试5:reverse(bfs+set 或 线段树优化建图)

题目: 分析: 首先画样例分析一下,会发现如果要求一个位置要多少次翻转,就将这个位置向与它关联的点连边(关联点指的是可能与它值互换的位置),一直连到起点为止,连边的次数即为它所需步数. 所以转换成求单源最短路,因为边权为1,可以用bfs. 但是这道题n的范围很大,刚刚的做法是n*k的,考虑优化. 法1:在建图上优化 题目要求的是区间翻转,所以也对应着相关性质:每个点连边一定是都连的奇数点或偶数点(画图可知),且这些奇数偶数点都对应着一段连续的区间. 如果可以将点向点连边优化成点向区间连边,复杂度

bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能够引爆的炸弹的显然应该是一个区间里面的,直接对这个区间进行线段树优化建图. 这样可以得到一个带环图,缩点以后这个炸弹能够炸到的炸弹就是从这个点能够走到的点. 但是这个不太好做,不过可以发现最终的炸弹也是一个区间,所以可以通过缩点后的 DAG 来求出左右端点. 时间复杂度 \(O(n\log n)\)