hdu 1540(线段树单点更新 区间合并)

来源:互联网 发布:待机长平板 知乎 编辑:程序博客网 时间:2024/06/05 05:57

解题思路:这一题要求的是连续区间,所以可以把它的子区间合并,这里运用线段树,但是在保存节点信息的方面要做一点修改

lsum:从这个区间的左端点往右能够找到的最大连续区间;

rsum:从这个区间的右端点往左能够找到的最大连续区间;

msum:表示这整个区间能够找到的最大连续区间;

sum:0表示这个区间还没有被破坏的点,大于0表示这个区间已经有被破坏的点。

接下来过程就是从大的区间逐渐分解小区间,然后逼近要求的点。。


这道题我一开始只记录了整个区间能够找到的最大连续区间,但这样就会有一个问题了,因为把[l,r]区间分解为[l,mid],[mid+1,r]区间,很有可能这个mid在最大连续区间里,这样就理所当然的要记录lsum和rsum了。


#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn = 50000;struct Segment{int l,r;int lsum,rsum,msum,sum;//sum表示该线段是否被有点被破坏}tree[maxn<<2];void PushUp(int rt){tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;if(tree[rt].sum){if(!tree[rt<<1].sum)tree[rt].lsum = tree[rt<<1].msum + tree[rt<<1|1].lsum;else tree[rt].lsum = tree[rt<<1].lsum;if(!tree[rt<<1|1].sum)tree[rt].rsum = tree[rt<<1|1].msum + tree[rt<<1].rsum;else tree[rt].rsum = tree[rt<<1|1].rsum;tree[rt].msum = max(tree[rt<<1].msum,tree[rt<<1|1].msum);tree[rt].msum = max(tree[rt].msum,tree[rt<<1].rsum + tree[rt<<1|1].lsum);}else{tree[rt].lsum = tree[rt].rsum = tree[rt].msum = tree[rt<<1].msum + tree[rt<<1|1].msum;}}void build(int rt,int l,int r){tree[rt].l = l, tree[rt].r = r;tree[rt].lsum = tree[rt].rsum = tree[rt].msum = 1;tree[rt].sum = 0;if(l == r) return;int mid = (l + r) >> 1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);PushUp(rt);}void insert(int rt,int t,int val){if(tree[rt].l == tree[rt].r){tree[rt].sum = val;if(tree[rt].sum){tree[rt].lsum = tree[rt].rsum = tree[rt].msum = 0;}else{tree[rt].lsum = tree[rt].rsum = tree[rt].msum = 1;}return;}int mid = (tree[rt].l + tree[rt].r) >> 1;if(t <= mid) insert(rt<<1,t,val);else insert(rt<<1|1,t,val);PushUp(rt);}int query(int rt,int t){if(tree[rt].l == tree[rt].r || !tree[rt].msum || !tree[rt].sum){return tree[rt].msum;}int mid = (tree[rt].l + tree[rt].r) >> 1;if(t <= mid){if(t >= mid - tree[rt<<1].rsum + 1)return tree[rt<<1].rsum + tree[rt<<1|1].lsum;else return query(rt<<1,t);}else{if(mid + tree[rt<<1|1].lsum >= t)return tree[rt<<1].rsum + tree[rt<<1|1].lsum;else return query(rt<<1|1,t);}}int main(){int n,m;char ch;while(cin >> n >> m){getchar();int id,top = 0,stack[maxn];build(1,1,n);while(m--){cin >> ch;if(ch == 'D'){cin >> id;stack[top++] = id;insert(1,id,1);}else if(ch == 'Q'){cin >> id;cout << query(1,id) << endl;}else if(ch == 'R'){id = stack[--top];insert(1,id,0);}}}return 0;}


0 0