您的位置:首页 > 其它

bzoj4046

2015-06-13 14:15 393 查看
分组赛的题……madan原题,考试想不出来真是SB得不行

首先,从大往小加边,每次加边如果成环必然弹出环上最大边

考虑询问[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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: