hdu 1540 Tunnel Warfare (线段树维护左右最长连续区间)
题意是一条线上的点,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点。
线段树结点 设置一个 ll 记录区间左端点开始的最大连续个数, rl 记录区间右端点开始的最大的连续个数,
ml表示该区间最大的连续点的个数。
View Code
线段树结点 设置一个 ll 记录区间左端点开始的最大连续个数, rl 记录区间右端点开始的最大的连续个数,
ml表示该区间最大的连续点的个数。
主要是更新和查询两个操作。
/*
key: ll,rl,ml;//左起最大长度,右起最大长度,区间最大长度
求与某点相连的连续最长距离。
线段树优化了求连续最长的时间,枚举是O(n),线段树O(log2[n])
*/
#include <cstdio>
#include <stack>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50005
int max3(int x, int y, int z)
{
x = x > y ? x : y;
return z > x ? z : x;
}
struct Seq
{
int ll,rl,ml;//左起最大长度,右起最大长度,区间最大长度
}seq[N<<2];
stack<int> st;
void build(int l, int r, int rt)
{
if(l==r)
seq[rt].ml = seq[rt].ll = seq[rt].rl = 1;
else
{
int m = (l + r) >> 1;
build(lson);
build(rson);
seq[rt].ml = seq[rt].ll = seq[rt].rl = seq[rt<<1].ml + seq[rt<<1|1].ml;
}
}
void update(int i, int add, int l, int r, int rt)
{
if(l==r)
{
seq[rt].ml = add;
seq[rt].ll = seq[rt].rl = seq[rt].ml;
}
else
{
int m = (l + r) >> 1;
if(i<=m)
update(i, add, lson);
else
update(i, add, rson);
seq[rt].ll = seq[rt<<1].ll;
if(m-l+1== seq[rt<<1].ml)//左孩子区间最大长度等于区间长度
seq[rt].ll += seq[rt<<1|1].ll;
seq[rt].rl = seq[rt<<1|1].rl;
if(r - m == seq[rt<<1|1].ml)//右孩子区间最大长度等于区间长度
seq[rt].rl += seq[rt<<1].rl;
//父亲节点区间最大长度 为 max(左孩子右起最大长度+右孩子左起最大长度 ,左孩子区间最大长度,右孩子区间最大长度)
seq[rt].ml = max3(seq[rt<<1].ml, seq[rt<<1|1].ml, seq[rt<<1].rl+seq[rt<<1|1].ll);
}
}
int query(int pos, int l, int r, int rt)
{
if(l==r || seq[rt].ml==0 || seq[rt].ml == r - l + 1)//叶子节点 或 区间最大长度等0 或 区间最大长度等于整个区间长度
return seq[rt].ml;
else
{
int m = (l + r) >> 1;
int ret = 0;
if(pos<=m)//查找点在左子树
{
ret = query(pos, l, m, rt<<1);
if(pos > m - seq[rt<<1].rl)//查找点在右起第一断点的右边
ret += seq[rt<<1|1].ll;
}
else//在右子树
{
ret = query(pos, m+1, r, rt<<1|1);
if(pos < m + 1 + seq[rt<<1|1].ll)//查找点在左起第一断点的左边
ret += seq[rt<<1].rl;
}
return ret;
}
}
int main()
{
int n, m, x;
char s[5];
while(scanf("%d%d", &n, &m)!=EOF)
{
build(1, n, 1);
while(!st.empty()) st.pop();
for(int i=1; i<=m; i++)
{
scanf("%s",s);
if(s[0]=='D')
{
scanf("%d",&x);
update(x, 0, 1, n, 1);
st.push(x);
}
else if(s[0]=='R')
{
x = st.top();
st.pop();
update(x, 1, 1, n, 1);
}
else if(s[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",query(x, 1, n, 1));
}
}
}
return 0;
}
key: ll,rl,ml;//左起最大长度,右起最大长度,区间最大长度
求与某点相连的连续最长距离。
线段树优化了求连续最长的时间,枚举是O(n),线段树O(log2[n])
*/
#include <cstdio>
#include <stack>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50005
int max3(int x, int y, int z)
{
x = x > y ? x : y;
return z > x ? z : x;
}
struct Seq
{
int ll,rl,ml;//左起最大长度,右起最大长度,区间最大长度
}seq[N<<2];
stack<int> st;
void build(int l, int r, int rt)
{
if(l==r)
seq[rt].ml = seq[rt].ll = seq[rt].rl = 1;
else
{
int m = (l + r) >> 1;
build(lson);
build(rson);
seq[rt].ml = seq[rt].ll = seq[rt].rl = seq[rt<<1].ml + seq[rt<<1|1].ml;
}
}
void update(int i, int add, int l, int r, int rt)
{
if(l==r)
{
seq[rt].ml = add;
seq[rt].ll = seq[rt].rl = seq[rt].ml;
}
else
{
int m = (l + r) >> 1;
if(i<=m)
update(i, add, lson);
else
update(i, add, rson);
seq[rt].ll = seq[rt<<1].ll;
if(m-l+1== seq[rt<<1].ml)//左孩子区间最大长度等于区间长度
seq[rt].ll += seq[rt<<1|1].ll;
seq[rt].rl = seq[rt<<1|1].rl;
if(r - m == seq[rt<<1|1].ml)//右孩子区间最大长度等于区间长度
seq[rt].rl += seq[rt<<1].rl;
//父亲节点区间最大长度 为 max(左孩子右起最大长度+右孩子左起最大长度 ,左孩子区间最大长度,右孩子区间最大长度)
seq[rt].ml = max3(seq[rt<<1].ml, seq[rt<<1|1].ml, seq[rt<<1].rl+seq[rt<<1|1].ll);
}
}
int query(int pos, int l, int r, int rt)
{
if(l==r || seq[rt].ml==0 || seq[rt].ml == r - l + 1)//叶子节点 或 区间最大长度等0 或 区间最大长度等于整个区间长度
return seq[rt].ml;
else
{
int m = (l + r) >> 1;
int ret = 0;
if(pos<=m)//查找点在左子树
{
ret = query(pos, l, m, rt<<1);
if(pos > m - seq[rt<<1].rl)//查找点在右起第一断点的右边
ret += seq[rt<<1|1].ll;
}
else//在右子树
{
ret = query(pos, m+1, r, rt<<1|1);
if(pos < m + 1 + seq[rt<<1|1].ll)//查找点在左起第一断点的左边
ret += seq[rt<<1].rl;
}
return ret;
}
}
int main()
{
int n, m, x;
char s[5];
while(scanf("%d%d", &n, &m)!=EOF)
{
build(1, n, 1);
while(!st.empty()) st.pop();
for(int i=1; i<=m; i++)
{
scanf("%s",s);
if(s[0]=='D')
{
scanf("%d",&x);
update(x, 0, 1, n, 1);
st.push(x);
}
else if(s[0]=='R')
{
x = st.top();
st.pop();
update(x, 1, 1, n, 1);
}
else if(s[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",query(x, 1, n, 1));
}
}
}
return 0;
}