Hdu 1540 求连续区间最大值的线段树
2018-02-24 23:42
483 查看
题意是原来有n个连续的村庄,然后这时候有可能炸毁一个村庄,或者修复一个村庄或者查询有多少村庄与这个村庄相连,n个村庄是从1到n左右相连,询问中的相连包括间接相连和直接相连。这道题我是没有想到怎么来维护
首先是build函数
其中的ml,mr,mx分别表示这个点被分成两部分之后的在l到r之间左半部分能取到的最大连续部分和右半部分能取到的最大连续部分和总的能取到的最大连续部分
然后是更新函数:
其中的flag表示是修复还是毁灭,flag=1表示修复,flag=0表示毁灭,然后这个更新函数首先要找到x的范围,然后开始更新ml:tree[num].ml=tree[num<<1].ml;我们首先把左子树的更新上来,然后看if(tree[num<<1].ml==tree[num<<1].r-tree[num<<1].l+1)左子树是不是满的,假如说是满的话,我们就能把右子树的左边加上来,同理,对待右子树我们也是这么操作
最后是查询操作:
查询操作首先看查询的点在左子树还是右子树,如果在左子树,我们就看查询的点与右子树有没有关系,如果有关系,我们就要查询这个查询点在左子树上相连的点+右子树相连的点,同理右子树也是如此
这道题应该是模板题,可自己连这都不会,哎
首先是build函数
void build(int num,int l,int r) { tree[num].ml=tree[num].mr=tree[num].mx=r-l+1; tree[num].l=l;tree[num].r=r; if(l==r) return ; int mid=(l+r)>>1; build(num<<1,l,mid); build(num<<1|1,mid+1,r); }
其中的ml,mr,mx分别表示这个点被分成两部分之后的在l到r之间左半部分能取到的最大连续部分和右半部分能取到的最大连续部分和总的能取到的最大连续部分
然后是更新函数:
void update(int num,int x,int flag) { if(tree[num].l==tree[num].r) { tree[num].ml=tree[num].mr=tree[num].mx=flag; return ; } int mid=(tree[num].l+tree[num].r)>>1; if(x<=mid) update(num<<1,x,flag); else update(num<<1|1,x,flag); tree[num].ml=tree[num<<1].ml; tree[num].mr=tree[num<<1|1].mr; tree[num].mx=max(tree[num<<1].mx,max(tree[num<<1|1].mx,tree[num<<1].mr+tree[num<<1|1].ml)); if(tree[num<<1].ml==tree[num<<1].r-tree[num<<1].l+1) tree[num].ml+=tree[num<<1|1].ml; if(tree[num<<1|1].mr==tree[num<<1|1].r-tree[num<<1|1].l+1) tree[num].mr+=tree[num<<1].mr; }
其中的flag表示是修复还是毁灭,flag=1表示修复,flag=0表示毁灭,然后这个更新函数首先要找到x的范围,然后开始更新ml:tree[num].ml=tree[num<<1].ml;我们首先把左子树的更新上来,然后看if(tree[num<<1].ml==tree[num<<1].r-tree[num<<1].l+1)左子树是不是满的,假如说是满的话,我们就能把右子树的左边加上来,同理,对待右子树我们也是这么操作
最后是查询操作:
int query(int num,int x) { if(tree[num].l==tree[num].r||tree[num].mx==0||tree[num].mx==tree[num].r-tree[num].l+1) return tree[num].mx; int mid=(tree[num].l+tree[num].r)>>1; if(x<=mid) { if(x>=tree[num<<1].r-tree[num<<1].mr+1) return query(num<<1,x)+query(num<<1|1,mid+1); else return query(num<<1,x); } else { if(x<=tree[num<<1|1].l+tree[num<<1|1].ml-1) return query(num<<1|1,x)+query(num<<1,mid); else return query(num<<1|1,x); } }
查询操作首先看查询的点在左子树还是右子树,如果在左子树,我们就看查询的点与右子树有没有关系,如果有关系,我们就要查询这个查询点在左子树上相连的点+右子树相连的点,同理右子树也是如此
这道题应该是模板题,可自己连这都不会,哎
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=5e4+5;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const LL LLINF=1e14;
stack<int>Q;
struct Node {
int ml,mr,mx;
int l,r;
}tree[maxn*4];
void build(int num,int l,int r) { tree[num].ml=tree[num].mr=tree[num].mx=r-l+1; tree[num].l=l;tree[num].r=r; if(l==r) return ; int mid=(l+r)>>1; build(num<<1,l,mid); build(num<<1|1,mid+1,r); }
void update(int num,int x,int flag) { if(tree[num].l==tree[num].r) { tree[num].ml=tree[num].mr=tree[num].mx=flag; return ; } int mid=(tree[num].l+tree[num].r)>>1; if(x<=mid) update(num<<1,x,flag); else update(num<<1|1,x,flag); tree[num].ml=tree[num<<1].ml; tree[num].mr=tree[num<<1|1].mr; tree[num].mx=max(tree[num<<1].mx,max(tree[num<<1|1].mx,tree[num<<1].mr+tree[num<<1|1].ml)); if(tree[num<<1].ml==tree[num<<1].r-tree[num<<1].l+1) tree[num].ml+=tree[num<<1|1].ml; if(tree[num<<1|1].mr==tree[num<<1|1].r-tree[num<<1|1].l+1) tree[num].mr+=tree[num<<1].mr; }
int query(int num,int x) { if(tree[num].l==tree[num].r||tree[num].mx==0||tree[num].mx==tree[num].r-tree[num].l+1) return tree[num].mx; int mid=(tree[num].l+tree[num].r)>>1; if(x<=mid) { if(x>=tree[num<<1].r-tree[num<<1].mr+1) return query(num<<1,x)+query(num<<1|1,mid+1); else return query(num<<1,x); } else { if(x<=tree[num<<1|1].l+tree[num<<1|1].ml-1) return query(num<<1|1,x)+query(num<<1,mid); else return query(num<<1|1,x); } }
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n,m,x;
while(cin>>n>>m) {
while(Q.size())Q.pop();
build(1,1,n);
for(int i=1;i<=m;i++) {
char c;
cin>>c;
if(c=='D') {
cin>>x;
Q.push(x);
update(1,x,0);
}
else if(c=='Q'){
cin>>x;
cout<<query(1,x)<<endl;
}
else {
if(Q.size()==0) continue;
x=Q.top();
Q.pop();
update(1,x,1);
}
}
}
return 0;
}
相关文章推荐
- hdu 1540 线段树 点所在的区间最大连续长度
- HDU 1540 Tunnel Warfare(线段树 区间合并 最大连续区间)
- HDU 1540 Tunnel Warfare(线段树,去最大连续区间)
- HDU 1540(线段树,以一点扩展开的最大连续区间)
- HDU 1540 Tunnel Warfare 【线段树--最大连续区间】
- HDU - 1540 Tunnel Warfare(线段树最大连续区间)
- hdu 3308 LCIS 最大连续递增字串长 线段树区间合并
- hdu1540(线段树维护连续区间模型)
- 文章标题 HDU 1540 : Tunnel Warfare (线段树+最大连续区间)
- HDU 1540 / POJ 2892 Tunnel Warfare (单点更新,区间合并,求包含某点的最大连续个数)
- hdu1540 线段树之区间左右连续询问
- hdu1540线段树连续区间
- hdu-1540(线段树+最大连续区间)
- HDU1540 Tunnel Warfare(线段树:维护最大连续子串)
- hdu 1540 Tunnel Warfare(线段树 连续区间)
- hdu 1540 Tunnel Warfare(单点更新,取最大连续区间)★
- hdu 1540 Tunnel Warfare (线段树维护左右最长连续区间)
- 【维护区间最长连续子序列 && 线段树 && 区间归并】HDU - 1540 Tunnel Warfare
- HDU 3308——LCIS(线段树,区间合并,最长连续递增子序列)
- hdu 1540 线段树区间合并