日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/3/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(线段树单点更新 区间合并)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。