bzoj4046
2015-06-13 14:15
393 查看
分组赛的题……madan原题,考试想不出来真是SB得不行
首先,从大往小加边,每次加边如果成环必然弹出环上最大边
考虑询问[x,y],如果边权在[x,y]的边弹出了小于等于y的边j,说明j不在最小生成树上
其余边权在[x,y]的边都在最小生成树上
因此我们每次只要询问,在一段区间内边权小于等于y的边权和是多少,显然用主席树维护
处理弹出的最大边可以暴力,因为n不大
但我写了lct还是t真是简直了……
View Code
首先,从大往小加边,每次加边如果成环必然弹出环上最大边
考虑询问[x,y],如果边权在[x,y]的边弹出了小于等于y的边j,说明j不在最小生成树上
其余边权在[x,y]的边都在最小生成树上
因此我们每次只要询问,在一段区间内边权小于等于y的边权和是多少,显然用主席树维护
处理弹出的最大边可以暴力,因为n不大
但我写了lct还是t真是简直了……
const inf=10000007; type way=record x,y,z:longint; end; node=record l,r,s:longint; end; var tree:array[0..210010*20] of node; a:array[0..100010] of way; h,st,w,f,c,fa,mx:array[0..120010] of longint; son:array[0..120010,1..2] of longint; rev:array[0..120010] of boolean; ans,j,len,wh,p,i,t,tt,n,m,q,x,y:longint; procedure swap(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c; end; procedure sort(l,r:longint); var i,j,x:longint; y:way; begin i:=l; j:=r; x:=a[(l+r) shr 1].z; repeat while a[i].z>x do inc(i); while x>a[j].z do dec(j); if not(i>j) then begin y:=a[i]; a[i]:=a[j]; a[j]:=y; inc(i); dec(j); end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; function max(a,b:longint):longint; begin if a>b then exit(a) else exit(b); end; function getf(x:longint):longint; begin if f[x]<>x then f[x]:=getf(f[x]); exit(f[x]); end; function root(x:longint):boolean; begin exit((son[fa[x],1]<>x) and (son[fa[x],2]<>x)); end; procedure update(x:longint); var l,r:longint; begin l:=son[x,1]; r:=son[x,2]; mx[x]:=x; if w[mx[l]]>w[mx[x]] then mx[x]:=mx[l]; if w[mx[r]]>w[mx[x]] then mx[x]:=mx[r]; end; procedure rotate(x,w:longint); var y:longint; begin y:=fa[x]; if not root(y) then begin if son[fa[y],1]=y then son[fa[y],1]:=x else son[fa[y],2]:=x; end; fa[x]:=fa[y]; son[y,3-w]:=son[x,w]; if son[x,w]<>0 then fa[son[x,w]]:=y; son[x,w]:=y; fa[y]:=x; update(y); end; procedure push(x:longint); begin if rev[x] then begin rev[son[x,1]]:=not rev[son[x,1]]; rev[son[x,2]]:=not rev[son[x,2]]; swap(son[x,1],son[x,2]); rev[x]:=false; end; end; procedure splay(x:longint); var i,y,t:longint; fl:boolean; begin i:=x; t:=0; while not root(i) do begin inc(t); st[t]:=i; i:=fa[i]; end; inc(t); st[t]:=i; for i:=t downto 1 do push(st[i]); if t=1 then exit; fl:=true; while fl do begin y:=fa[x]; if y=st[t] then begin if son[y,1]=x then rotate(x,2) else rotate(x,1); fl:=false; end else begin if fa[y]=st[t] then fl:=false; if son[fa[y],1]=y then begin if son[y,1]=x then rotate(y,2) else rotate(x,1); rotate(x,2); end else begin if son[y,1]=x then rotate(x,2) else rotate(y,1); rotate(x,1); end; end; end; update(x); end; procedure access(x:longint); var y:longint; begin y:=0; repeat splay(x); son[x,2]:=y; update(x); y:=x; x:=fa[x]; until x=0; end; procedure makeroot(x:longint); begin access(x); splay(x); rev[x]:=not rev[x]; end; procedure link(x,y:longint); begin makeroot(x); fa[x]:=y; end; procedure cut(x,y:longint); begin makeroot(x); access(y); splay(y); son[y,1]:=0; fa[x]:=0; end; function get(x,y:longint):longint; begin makeroot(x); access(y); splay(y); exit(mx[y]); end; function build(l,r:longint):longint; var m,q:longint; begin inc(t); q:=t; tree[q].s:=0; if l<>r then begin m:=(l+r) shr 1; tree[q].l:=build(l,m); tree[q].r:=build(m+1,r); end; exit(q); end; function add(l,r,last,x,y:longint):longint; var m,q:longint; begin inc(t); q:=t; if l=r then tree[q].s:=tree[last].s+c[x]*y else begin m:=(l+r) shr 1; if x<=m then begin tree[q].r:=tree[last].r; tree[q].l:=add(l,m,tree[last].l,x,y); end else begin tree[q].l:=tree[last].l; tree[q].r:=add(m+1,r,tree[last].r,x,y); end; tree[q].s:=tree[tree[q].l].s+tree[tree[q].r].s; end; exit(q); end; function ask(l,r,x,y,k:longint):longint; var m:longint; begin if l=r then begin if c[l]<=k then exit(tree[y].s-tree[x].s) else exit(0); end else begin m:=(l+r) shr 1; if k<=c[m] then exit(ask(l,m,tree[x].l,tree[y].l,k)) else exit(tree[tree[y].l].s-tree[tree[x].l].s+ask(m+1,r,tree[x].r,tree[y].r,k)); end; end; function find1(l,r,x:longint):longint; var m:longint; begin find1:=r+1; while l<=r do begin m:=(l+r) shr 1; if (c[a[m-1].z]>x) and (c[a[m].z]<=x) then exit(m); if c[a[m].z]<=x then r:=m-1 else l:=m+1; end; end; function find2(l,r,x:longint):longint; var m:longint; begin find2:=l-1; while l<=r do begin m:=(l+r) shr 1; if (c[a[m].z]>=x) and (c[a[m+1].z]<x) then exit(m); if c[a[m].z]>=x then l:=m+1 else r:=m-1; end; end; begin readln(tt); while tt>0 do begin dec(tt); readln(n,m); for i:=1 to n+m do begin f[i]:=i; fa[i]:=0; son[i,1]:=0; son[i,2]:=0; w[i]:=0; rev[i]:=false; end; for i:=1 to m do readln(a[i].x,a[i].y,a[i].z); sort(1,m); for i:=1 to m do w[n+i]:=a[i].z; p:=1; c[1]:=a[m].z; a[m].z:=1; for i:=m-1 downto 1 do begin if a[i].z<>c[p] then begin inc(p); c[p]:=a[i].z; end; a[i].z:=p; end; t:=0; h[0]:=build(1,p); for i:=1 to m do begin x:=getf(a[i].x); y:=getf(a[i].y); h[i]:=h[i-1]; if x<>y then f[x]:=y else begin wh:=get(a[i].x,a[i].y); h[i]:=add(1,p,h[i],a[wh-n].z,-1); cut(a[wh-n].x,wh); cut(a[wh-n].y,wh); end; h[i]:=add(1,p,h[i],a[i].z,1); link(a[i].x,n+i); link(a[i].y,n+i); end; c[p+1]:=inf; a[0].z:=p+1; a[m+1].z:=0; c[0]:=-1; readln(q); ans:=0; for i:=1 to q do begin readln(x,y); x:=x-ans; y:=y-ans; len:=y; if x>y then ans:=0 else begin x:=find2(1,m,x); y:=find1(1,m,y); ans:=ask(1,p,h[y-1],h[x],len); end; writeln(ans); end; end; end.
View Code
相关文章推荐
- iOS 之 Thread Runloop浅显认识说起
- FaceBook/infer-分析OC文件
- Sprite Kit Swift游戏开发新手指导手册(2)
- 磁盘文件系统Fat、Fat32、NTFS、exFAT的优缺点
- 1. 推荐引擎初探
- asp.net sql 分页,,优化 排序 及分页,
- RSA 公钥密码实验1
- 16.4 监视 AlwaysOn 可用性组
- Leetcode: Sort List
- 混合自回归移动平均过程
- 数据库远程还原,本地备份。
- leetCode:Count Complete Tree Nodes
- Shell中的循环语句for、while、until实例讲解
- oracle包
- Transpose File
- 利用 僵尸环境变量 找出Crash原因( 僵尸断点 )
- 推荐算法:基于特征的推荐算法
- java 封装mysql
- 字符串中的转义字符与字符串的长度
- jquery源码之延迟对象--Deferred