bzoj3551 3545

我直接来讲在线好了

这是一个很巧妙的方法,把边作为一个点

做一遍最小生成树,当加如一条边时,我们把这条边两点x,y的并查集的根i,j的父亲都设为这条边代表的点k,由k向i,j连边

这样我们就构建出一棵树,这棵树的叶子都是原来节点

且每棵子树都是在子树根所代表的边的限制下的最小连通块

这样我们就可以通过dfs序(只用对叶子标号)+主席树来维护k大了并通过倍增找到限制

这两题都是一副卡pascal过不了的样子……QAQ

另外网上的一些标称(bzoj3551)似乎没有考虑一个点没有边可走,但询问k=1的情况,可以加数据cha

  1 type node=record
  2        po,next:longint;
  3      end;
  4      way=record
  5        x,y,z:longint;
  6      end;
  7      point=record
  8        l,r,s:longint;
  9      end;
 10
 11 var e:array[0..400010] of node;
 12     w:array[0..500010] of way;
 13     v:array[0..400010] of boolean;
 14     anc:array[0..200010,0..20] of longint;
 15     d,l,r,p,fa,c,a,b,h:array[0..200010] of longint;
 16     tree:array[0..200010*20] of point;
 17     num,j,s,size,i,len,t,n,m,q,x,y,ans,k:longint;
 18
 19 function min(a,b:longint):longint;
 20   begin
 21     if a>b then exit(b) else exit(a);
 22   end;
 23
 24 function max(a,b:longint):longint;
 25   begin
 26     if a>b then exit(a) else exit(b);
 27   end;
 28
 29 function getf(x:longint):longint;
 30   begin
 31     if fa[x]<>x then fa[x]:=getf(fa[x]);
 32     exit(fa[x]);
 33   end;
 34
 35 procedure swap(var a,b:longint);
 36   var c:longint;
 37   begin
 38     c:=a;
 39     a:=b;
 40     b:=c;
 41   end;
 42
 43 procedure sort(l,r:longint);
 44   var i,j,x:longint;
 45   begin
 46     i:=l;
 47     j:=r;
 48     x:=a[(l+r) shr 1];
 49     repeat
 50       while a[i]<x do inc(i);
 51       while x<a[j] do dec(j);
 52       if i<=j then
 53       begin
 54         swap(a[i],a[j]);
 55         swap(b[i],b[j]);
 56         inc(i);
 57         dec(j);
 58       end;
 59     until i>j;
 60     if l<j then sort(l,j);
 61     if i<r then sort(i,r);
 62   end;
 63
 64 procedure qsort(l,r:longint);
 65   var i,j,x:longint;
 66       y:way;
 67   begin
 68     i:=l;
 69     j:=r;
 70     x:=w[(l+r) shr 1].z;
 71     repeat
 72       while w[i].z<x do inc(i);
 73       while x<w[j].z do dec(j);
 74       if i<=j then
 75       begin
 76         y:=w[i]; w[i]:=w[j]; w[j]:=y;
 77         inc(i);
 78         dec(j);
 79       end;
 80     until i>j;
 81     if l<j then qsort(l,j);
 82     if i<r then qsort(i,r);
 83   end;
 84
 85 procedure dfs(x:longint);
 86   var i,y:longint;
 87   begin
 88     v[x]:=true;
 89     if x<=n then
 90     begin
 91       inc(num);
 92       b[num]:=x;
 93       l[x]:=num;
 94       r[x]:=num;
 95       exit;
 96     end;
 97     i:=p[x];
 98     l[x]:=n;
 99     r[x]:=0;
100     while i<>0 do
101     begin
102       y:=e[i].po;
103       anc[y,0]:=x;
104       dfs(y);
105       l[x]:=min(l[x],l[y]);
106       r[x]:=max(r[x],r[y]);
107       i:=e[i].next;
108     end;
109   end;
110
111 function find(x,y:longint):longint;
112   var i:longint;
113   begin
114     for i:=size downto 0 do
115       if a[anc[x,i]]<=y then x:=anc[x,i];
116     exit(x);
117   end;
118
119 function build(l,r:longint):longint;
120   var m,q:longint;
121   begin
122     inc(t);
123     q:=t;
124     if l<>r then
125     begin
126       m:=(l+r) shr 1;
127       tree[q].l:=build(l,m);
128       tree[q].r:=build(m+1,r);
129     end;
130     exit(q);
131   end;
132
133 function add(l,r,last,x:longint):longint;
134   var m,q:longint;
135   begin
136     inc(t);
137     q:=t;
138     if l=r then tree[q].s:=tree[last].s+1
139     else begin
140       m:=(l+r) shr 1;
141       if x<=m then
142       begin
143         tree[q].r:=tree[last].r;
144         tree[q].l:=add(l,m,tree[last].l,x);
145       end
146       else begin
147         tree[q].l:=tree[last].l;
148         tree[q].r:=add(m+1,r,tree[last].r,x);
149       end;
150       tree[q].s:=tree[tree[q].l].s+tree[tree[q].r].s;
151     end;
152     exit(q);
153   end;
154
155 function ask(l,r,x,y,k:longint):longint;
156   var m,s:longint;
157   begin
158     if l=r then exit(c[l])
159     else begin
160       m:=(l+r) shr 1;
161       s:=tree[tree[y].r].s-tree[tree[x].r].s;
162       if s>=k then exit(ask(m+1,r,tree[x].r,tree[y].r,k))
163       else exit(ask(l,m,tree[x].l,tree[y].l,k-s));
164     end;
165   end;
166
167 procedure ins(x,y:longint);
168   begin
169     inc(len);
170     e[len].po:=y;
171     e[len].next:=p[x];
172     p[x]:=len;
173   end;
174
175 begin
176   readln(n,m,q);
177   for i:=1 to n do
178   begin
179     read(d[i]);
180     a[i]:=d[i];
181     b[i]:=i;
182   end;
183   sort(1,n);
184   s:=1;
185   d[b[1]]:=1;
186   c[1]:=a[1];
187   for i:=2 to n do
188   begin
189     if a[i]<>a[i-1] then
190     begin
191       inc(s);
192       c[s]:=a[i];
193     end;
194     d[b[i]]:=s;
195   end;
196   for i:=1 to 2*n do
197     fa[i]:=i;
198   for i:=1 to m do
199     readln(w[i].x,w[i].y,w[i].z);
200
201   qsort(1,m);
202   t:=n;
203   fillchar(a,sizeof(a),0);
204   for i:=1 to m do
205   begin
206     x:=getf(w[i].x);
207     y:=getf(w[i].y);
208     if x<>y then
209     begin
210       inc(t);
211       fa[x]:=t;
212       fa[y]:=t;
213       a[t]:=w[i].z;
214       ins(t,x);
215       ins(t,y);
216       if t=2*n-1 then break;
217     end;
218   end;
219
220   a[0]:=2147483647;
221   len:=t;
222   for i:=1 to len do
223     if not v[i] then dfs(getf(i));
224   size:=trunc(ln(len)/ln(2)+0.1);
225   for j:=1 to size do
226     for i:=1 to len do
227     begin
228       x:=anc[i,j-1];
229       anc[i,j]:=anc[x,j-1];
230     end;
231   t:=0;
232   h[0]:=build(1,s);
233   for i:=1 to num do
234     h[i]:=add(1,s,h[i-1],d[b[i]]);
235   ans:=-1;
236   for i:=1 to q do
237   begin
238     readln(x,y,k);
239    { if ans<>-1 then
240     begin
241       x:=x xor ans;
242       y:=y xor ans;
243       k:=k xor ans;
244     end;        }
245     x:=find(x,y);
246     if x<=n then
247     begin
248       if k=1 then ans:=c[d[x]]
249       else ans:=-1;
250     end
251     else if tree[h[r[x]]].s-tree[h[l[x]-1]].s<k then ans:=-1
252     else ans:=ask(1,s,h[l[x]-1],h[r[x]],k);
253     writeln(ans);
254   end;
255 end.

时间: 2024-11-05 12:17:09

bzoj3551 3545的相关文章

【BZOJ 3545】【ONTAK 2010】Peaks &amp; 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树

sunshine的A题我竟然调了一周!!! 把循环dfs改成一个dfs就可以,,,我也不知道为什么这样就不会RE,但它却是A了,,, 这周我一直在调这个题,总结一下智障错误: 1.倍增的范围设成了n而不是n*2-1,,, 2.重构树的顶点是n*2-1,而我一开始设成了n,,, 3.define里的for3和for4的i--打成i++,,,,,,,,,,,, 4.dfs爆栈了,找CA爷问的编译命令里手动扩栈,真是愚蠢的问题,,,, 比赛时绝不会有太多时间,在这么犯逗就得滚粗了QAQ 3545: #

bzoj3551 [ONTAK2010]Peaks加强版

Description //[题目描述]同3545 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表

bzoj 3545&amp;&amp;3551: [ONTAK2010]Peaks &amp;&amp;加强版 平衡树&amp;&amp;并查集合并树&amp;&amp;主席树

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

[您有新的未分配科技点][BZOJ3545&amp;BZOJ3551]克鲁斯卡尔重构树

这次我们来搞一个很新奇的知识点:克鲁斯卡尔重构树.它也是一种图,是克鲁斯卡尔算法求最小生成树的升级版首先看下面一个问题:BZOJ3545 Peaks. 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走. 现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1.N<=1e5,M,Q<=5*1e5 上面这个题没有要求在线,因此我们可以离线构造

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MB Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q.第二行N个数,第i个数为h_i接下来M行,每行

bzoj3545 [ONTAK2010]Peaks、bzoj3551 [ONTAK2010]Peaks加强版

题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(强制在线): #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; const int M = 5*N; template<typename T> inline void read(T&x) {

bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版

传送门:bzoj  bzoj wdnmd为什么加强版不是权限题原题却是啊 3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达

bzoj3545 &amp;&amp; bzoj3551 Peaks(离线版&amp;&amp;在线版)

题目给n点m边的无向图,有点权和边权 每次询问求点v在经过路径上的边都不超过w的情况下,能到达的第k大的点的权值 首先离线版比较容易想到,属于我现在能码出来的最难的码农题之一吧T T 这道题思路是这样的 1.对于边权的限制条件,可以先想到做一棵最小生成树 2.对于第k大这种询问,可以建权值线段树,但是山的高度太大到1e9,所以我们还要先离散化到1e6的水平才能用线段树 3.显然不能对每个询问w都建线段树,因此要用到主席树.具体做法是将询问和边权都排序(详情看代码),给每个点建一棵线段树,然后边建

bzoj3551 Peaks加强版 题解

这个题--感觉离线和在线的代码难度差不多(pb_ds不要说话). 离线的话,就是把所有询问按照w排个序,然后一边Kruskal+平衡树启发式合并一边回答询问就好了. 在线也不难写.首先Kruskal重构树(这个Kruskal重构树是不按秩合并还要添虚点的那种--),那么每个点可以到达的点一定在某个子树里.子树的dfs序是连续的,所以可以对dfs序建主席树来求区间k大.又因为只有叶子节点的点权是有意义的,所以可以只对叶子的dfs序建主席树.查询的时候倍增跳到最高的w<=询问的w的点然后主席树就好了