hdu 1540(线段树单点更新 区间合并)
生活随笔
收集整理的這篇文章主要介紹了
hdu 1540(线段树单点更新 区间合并)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
解題思路:這一題要求的是連續區間,所以可以把它的子區間合并,這里運用線段樹,但是在保存節點信息的方面要做一點修改
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; }
總結
以上是生活随笔為你收集整理的hdu 1540(线段树单点更新 区间合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信公众帐号开发教程第17篇-应用实例之
- 下一篇: 开发指南专题十七-JEECG图表配置说明