您的位置:首页 > 其它

Hdu 1540 求连续区间最大值的线段树

2018-02-24 23:42 483 查看
题意是原来有n个连续的村庄,然后这时候有可能炸毁一个村庄,或者修复一个村庄或者查询有多少村庄与这个村庄相连,n个村庄是从1到n左右相连,询问中的相连包括间接相连和直接相连。这道题我是没有想到怎么来维护

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