poj1823,3667
2013-12-14 20:05
295 查看
又来练线段树了……
poj1823题意很简单(明显的数据结构题),区间修改和统计最长连续空区间;
有了poj3468的基础,区间修改不是什么问题了,重点是求最长连续空区间;(弱弱的我纠结了好久)
在每个节点上增加3个域,lmax,rmax,maxx,分别表示从左起最长,右起最长,区间内最长,然后稍稍动点脑筋即可……
附代码:
type node=record
lmax,rmax,maxx:longint;
l,r,lazy:integer; //lazy表示区间三种情况,-1表示区间内有人住但未满,0表示无人住,1表示全住满
end;
var tree:array[0..80000] of node;
i,n,m,a,b,c,j:longint;
procedure updata(i:longint); //更新
var p:longint;
begin
if tree[i].lazy<>-1 then
begin
if tree[i].lazy=0 then p:=tree[i].r-tree[i].l+1 else p:=0;
tree[i].lmax:=p;
tree[i].rmax:=p;
tree[i].maxx:=p;
end
else begin //看起来很繁琐,实际上仔细想想就明白了
tree[i].lmax:=tree[i*2].lmax;
if tree[i].lmax=tree[i*2].r-tree[i*2].l+1 then tree[i].lmax:=tree[i].lmax+tree[i*2+1].lmax;
tree[i].rmax:=tree[i*2+1].rmax;
if tree[i].rmax=tree[i*2+1].r-tree[i*2+1].l+1 then tree[i].rmax:=tree[i].rmax+tree[i*2].rmax;
p:=max(tree[i].lmax,tree[i].rmax);
p:=max(p,max(tree[i*2].maxx,tree[i*2+1].maxx));
tree[i].maxx:=max(p,tree[i*2].rmax+tree[i*2+1].lmax);
end;
end;
procedure pushdown(i:longint); //lazy思想,注意标记下移的时候不忘更新,因为某个子区间不一定会被访问
begin
tree[i*2].lazy:=tree[i].lazy;
updata(i*2);
tree[i*2+1].lazy:=tree[i].lazy;
updata(i*2+1);
tree[i].lazy:=-1; //需要标记下移的时候当前区间一定不会是全满或全空(想想为什么)
end;
procedure build(i,l,r:longint); //初始化线段树
var m:longint;
begin
tree[i].l:=l; tree[i].r:=r;
tree[i].lazy:=0;
updata(i);
if l<>r then
begin
m:=(l+r) div 2;
build(i*2,l,m);
build(i*2+1,m+1,r);
end;
end;
procedure work(i,l,r,t:longint);
var m:longint;
begin
if (l>=a) and (r<=b) then
begin
tree[i].lazy:=t;
updata(i);
end
else if l<>r then begin
if tree[i].lazy<>-1 then pushdown(i);
m:=(l+r) div 2;
if (a<=m) then work(i*2,l,m,t);
if (b>=m+1) then work(i*2+1,m+1,r,t);
updata(i); // 左右子区间访问过后更新当前区间
end;
end;
begin
readln(n,m);
build(1,1,n);
for i:=1 to m do
begin
read(c);
if c<>3 then
begin
readln(a,b);
b:=a+b-1;
if c=1 then work(1,1,n,1) else work(1,1,n,0); //1代表入住,0代表退房
end
else if c=3 then writeln(tree[1].maxx);
end;
end.
话说线段树查起来真累(难道还是我太渣了?),耗了5次才AC
poj3667在poj1823基础上多了个查找但并不难,对于当前区间,按照从左区间到右区间的优先顺序找即可,一次AC
poj1823题意很简单(明显的数据结构题),区间修改和统计最长连续空区间;
有了poj3468的基础,区间修改不是什么问题了,重点是求最长连续空区间;(弱弱的我纠结了好久)
在每个节点上增加3个域,lmax,rmax,maxx,分别表示从左起最长,右起最长,区间内最长,然后稍稍动点脑筋即可……
附代码:
type node=record
lmax,rmax,maxx:longint;
l,r,lazy:integer; //lazy表示区间三种情况,-1表示区间内有人住但未满,0表示无人住,1表示全住满
end;
var tree:array[0..80000] of node;
i,n,m,a,b,c,j:longint;
procedure updata(i:longint); //更新
var p:longint;
begin
if tree[i].lazy<>-1 then
begin
if tree[i].lazy=0 then p:=tree[i].r-tree[i].l+1 else p:=0;
tree[i].lmax:=p;
tree[i].rmax:=p;
tree[i].maxx:=p;
end
else begin //看起来很繁琐,实际上仔细想想就明白了
tree[i].lmax:=tree[i*2].lmax;
if tree[i].lmax=tree[i*2].r-tree[i*2].l+1 then tree[i].lmax:=tree[i].lmax+tree[i*2+1].lmax;
tree[i].rmax:=tree[i*2+1].rmax;
if tree[i].rmax=tree[i*2+1].r-tree[i*2+1].l+1 then tree[i].rmax:=tree[i].rmax+tree[i*2].rmax;
p:=max(tree[i].lmax,tree[i].rmax);
p:=max(p,max(tree[i*2].maxx,tree[i*2+1].maxx));
tree[i].maxx:=max(p,tree[i*2].rmax+tree[i*2+1].lmax);
end;
end;
procedure pushdown(i:longint); //lazy思想,注意标记下移的时候不忘更新,因为某个子区间不一定会被访问
begin
tree[i*2].lazy:=tree[i].lazy;
updata(i*2);
tree[i*2+1].lazy:=tree[i].lazy;
updata(i*2+1);
tree[i].lazy:=-1; //需要标记下移的时候当前区间一定不会是全满或全空(想想为什么)
end;
procedure build(i,l,r:longint); //初始化线段树
var m:longint;
begin
tree[i].l:=l; tree[i].r:=r;
tree[i].lazy:=0;
updata(i);
if l<>r then
begin
m:=(l+r) div 2;
build(i*2,l,m);
build(i*2+1,m+1,r);
end;
end;
procedure work(i,l,r,t:longint);
var m:longint;
begin
if (l>=a) and (r<=b) then
begin
tree[i].lazy:=t;
updata(i);
end
else if l<>r then begin
if tree[i].lazy<>-1 then pushdown(i);
m:=(l+r) div 2;
if (a<=m) then work(i*2,l,m,t);
if (b>=m+1) then work(i*2+1,m+1,r,t);
updata(i); // 左右子区间访问过后更新当前区间
end;
end;
begin
readln(n,m);
build(1,1,n);
for i:=1 to m do
begin
read(c);
if c<>3 then
begin
readln(a,b);
b:=a+b-1;
if c=1 then work(1,1,n,1) else work(1,1,n,0); //1代表入住,0代表退房
end
else if c=3 then writeln(tree[1].maxx);
end;
end.
话说线段树查起来真累(难道还是我太渣了?),耗了5次才AC
poj3667在poj1823基础上多了个查找但并不难,对于当前区间,按照从左区间到右区间的优先顺序找即可,一次AC
相关文章推荐
- poj 1465 一题非常经典的bfs题
- hdu 1026 简单的bfs
- hdu1728 很有难度的bfs…
- poj 1733 并查集+偏移向…
- poj 1182 并查集经典题…
- poj 1611 并查集训练
- poj 1703 并查集的拓展
- HDU 4277 USACO ORZ
- poj 1836 最长增长序列的变形
- 集合中子集的生成算法
- poj 1742
- LA 4726 Average
- 动态规划求 最长递增子序列
- 01背包和完全背包比较容易忽略的地…
- Distant Galaxy poj 3141
- unipue() 函数的功能
- poj 2015 Permutation Code
- poj 1088 经典的记忆化搜索
- 中位数的应用
- poj 1724