HDU - 1540 Tunnel Warfare(线段树+区间合并)
生活随笔
收集整理的這篇文章主要介紹了
HDU - 1540 Tunnel Warfare(线段树+区间合并)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給定n個村莊,初始化全部連接為一條直線,需要依次執行m個操作,D表示摧毀第i個村莊的連接,R表示恢復最后一
個被摧毀的村莊的連接,Q表示詢問包括本身在內,與第i個村莊相連接的有多少個村莊(間接連接也算)
題目分析:這個題需要用到區間合并的思想,并且用線段樹來實現,應該算是個裸題了,把pushup的板子套進線段樹里就OK,
不過這個題的query函數比較難寫,我會在代碼中寫上相應注釋來幫助理解,其余的函數就都是線段樹的基礎了
上代碼:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<sstream> #include<cmath> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=5e4+100;struct Node {int l,r;int ll,rr,all; }tree[N<<2];void build(int k,int l,int r) {tree[k].l=l;tree[k].r=r;tree[k].all=tree[k].ll=tree[k].rr=r-l+1;if(l==r)return;int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r); }void pushup(int k)//注意對三個參數上傳的技巧 {tree[k].ll=tree[k<<1].ll;if(tree[k].ll==tree[k<<1].r-tree[k<<1].l+1)tree[k].ll+=tree[k<<1|1].ll;tree[k].rr=tree[k<<1|1].rr;if(tree[k].rr==tree[k<<1|1].r-tree[k<<1|1].l+1)tree[k].rr+=tree[k<<1].rr;tree[k].all=max(tree[k<<1].rr+tree[k<<1|1].ll,max(tree[k<<1].all,tree[k<<1|1].all));return; }void update(int k,int pos,int val) {if(tree[k].l==tree[k].r){tree[k].all=tree[k].ll=tree[k].rr=val;return;}int mid=(tree[k].r+tree[k].l)>>1;if(mid>=pos)update(k<<1,pos,val);elseupdate(k<<1|1,pos,val);pushup(k); }int query(int k,int pos) {if(tree[k].all==0)return 0;if(tree[k].l+tree[k].ll>pos)//判斷是否在左區間 pos<左端點+左連續return tree[k].ll;if(tree[k].r-tree[k].rr<pos)//判斷是否在右區間 pos>右端點-右連續 return tree[k].rr;if(pos>tree[k<<1].r-tree[k<<1].rr&&pos<tree[k<<1|1].l+tree[k<<1|1].ll)//判斷是否在中間的區間 //右端點-右連續<pos<左端點+左連續return tree[k<<1].rr+tree[k<<1|1].ll;int mid=(tree[k].l+tree[k].r)>>1;if(mid>=pos)//如果上述條件不滿足,繼續向下遞歸判斷return query(k<<1,pos);elsereturn query(k<<1|1,pos); }int main() { // freopen("input.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)!=EOF){build(1,1,n);stack<int>st;while(m--){char s[5];scanf("%s",s);if(s[0]=='D'){int num;scanf("%d",&num);st.push(num);update(1,num,0);}else if(s[0]=='R'){if(!st.empty()){update(1,st.top(),1);st.pop();}}else{int num;scanf("%d",&num);cout<<query(1,num)<<endl;}}}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 1540 Tunnel Warfare(线段树+区间合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)区间合并pushup函数模板
- 下一篇: HDU - 3667 Hotel(线段树