算法:线段树+贪心
老朋友又见面了,这次又没认出他来。。。
读完整个代码以后,发现这道题目还是比较容易理解的,想到要动态修改区间了但是没有多想。
用线段树的目的是求最小值,因为如果满足一个要求的话就看能否满足这个最小值的要求了,如果最小的都满足不了那么就无法满足这个奶牛的要求了。
tree记录值的时候需要记录两个值,一个是当前区间的最小值,一个是向下进行修改的值。
老朋友又见面了,这次又没认出他来。。。
读完整个代码以后,发现这道题目还是比较容易理解的,想到要动态修改区间了但是没有多想。
用线段树的目的是求最小值,因为如果满足一个要求的话就看能否满足这个最小值的要求了,如果最小的都满足不了那么就无法满足这个奶牛的要求了。
tree记录值的时候需要记录两个值,一个是当前区间的最小值,一个是向下进行修改的值。
快排的目的是分出一个段来,能保证左右两边都取最短的,既满足了我们要进行贪心的性质(即先选最短的进行满足),同时也保证了线段树分成左右两区间的性质。
program balloc;
const
maxn=100000;
type
tre=record
l,r,lc,rc,data,mindata:longint;
end;
atp=record
l,r:longint;
end;
var
n,m,tot,ans,root:longint;
tree:array [0..maxn*4] of tre;
tnt:array [0..maxn] of atp;
a:array [0..maxn] of longint;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
procedure build(var t:longint;l,r:longint);
var
mid:longint;
begin
inc(tot);
t:=tot;
tree[t].l:=l;
tree[t].r:=r;
if l=r then
begin
tree[t].mindata:=a[l];
exit;
end;
mid:=(l+r) shr 1;
build(tree[t].lc,l,mid);
build(tree[t].rc,mid+1,r);
tree[t].mindata:=min(tree[tree[t].lc].mindata,tree[tree[t].rc].mindata);
end;
procedure qsort(l,r:longint);
var
i,j,mm,mid1,mid2:longint;
t:atp;
begin
i:=l;
j:=r;
mm:=(l+r) shr 1;
mid1:=tnt[mm].r;
mid2:=tnt[mm].l;
repeat
while (tnt[i].r<mid1) or ((tnt[i].r=mid1) and (tnt[i].l>mid2)) do inc(i);
while (tnt[j].r>mid1) or ((tnt[j].r=mid1) and (tnt[j].r<mid2)) do dec(j);
if i<=j then
begin
t:=tnt[i];
tnt[i]:=tnt[j];
tnt[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure init;
var
i,mini:longint;
begin
readln(n,m);
for i:=1 to n do readln(a[i]);
build(root,1,n);
for i:=1 to m do readln(tnt[i].l,tnt[i].r);
qsort(1,m);
end;
procedure pass(t,add:longint);
begin
inc(tree[tree[t].lc].data,add);
inc(tree[tree[t].rc].data,add);
inc(tree[tree[t].lc].mindata,add);
inc(tree[tree[t].rc].mindata,add);
tree[t].data:=0;
end;
function get(l,r,t:longint):longint;
var
ans1,ans2:longint;
begin
if tree[t].data<>0 then pass(t,tree[t].data);
if (tree[t].l=l) and (tree[t].r=r) then exit(tree[t].mindata);
ans1:=maxlongint;
ans2:=maxlongint;
if r<=tree[tree[t].lc].r then ans1:=get(l,r,tree[t].lc)
else if l>=tree[tree[t].rc].l then ans2:=get(l,r,tree[t].rc)
else
begin
ans1:=get(l,tree[tree[t].lc].r,tree[t].lc);
ans2:=get(tree[tree[t].rc].l,r,tree[t].rc);
end;
exit(min(ans1,ans2));
end;
procedure change(l,r,x,t:longint);
begin
if (tree[t].l=l) and (tree[t].r=r) then
begin
inc(tree[t].data,x);
inc(tree[t].mindata,x);
exit;
end;
if tree[t].data<>0 then pass(t,tree[t].data);
if r<=tree[tree[t].lc].r then change(l,r,x,tree[t].lc)
else if l>=tree[tree[t].rc].l then change(l,r,x,tree[t].rc)
else
begin
change(l,tree[tree[t].lc].r,x,tree[t].lc);
change(tree[tree[t].rc].l,r,x,tree[t].rc);
end;
tree[t].mindata:=min(tree[tree[t].lc].mindata,tree[tree[t].rc].mindata);
end;
procedure main;
var
i,mini:longint;
begin
for i:=1 to m do
begin
mini:=get(tnt[i].l,tnt[i].r,root);
if mini>0 then
begin
inc(ans);
change(tnt[i].l,tnt[i].r,-1,root);
end;
end;
writeln(ans);
end;
begin
assign(input,'balloc.in'); reset(input);
assign(output,'balloc.out'); rewrite(output);
init;
main;
close(input); close(output);
end.
本文探讨了如何运用线段树和贪心算法解决动态修改区间问题,通过实例解析实现步骤,并展示了快排在算法优化过程中的作用。
142

被折叠的 条评论
为什么被折叠?



