[线段树] (i) hdu1540 (区间合并)
如在阅读本文时遇到不懂的部分,请在评论区询问,或跳转 线段树总介绍
推荐先阅读 (线段树) (h) poj3667 (区间合并) 以获得线段树区间合并的一些知识
本题与上题(poj3667)基本相同,但要注意询问部分要求的是包含x的0区间长度
query (看看代码,倒也直观,很容易理解)
int query(int rt,int l,int r,int x){ if(l==r||!MaxiLen[rt]||MaxiLen[rt]==r-l+1)return MaxiLen[rt]; //找到x ||含x的区间全是0 || 含x的区间全是1
//自己看看分别会返回什么...MaxiLen维护区间内最长的0
int mid=l+r>>1; if(x<=mid){ if(x>=mid-last[LS]+1)return last[LS]+pre[RS]; //夹中间 else return query(LS,l,mid,x); //LS }else{ if(x<=mid+pre[RS])return last[LS]+pre[RS]; //夹中间 else return query(RS,mid+1,r,x); //RS } }
左右去找x十分普通,重点是夹在中间的情况,要分左右区间的前驱后继来看;以及整个区间的特殊情况判定 if(l==r||!MaxiLen[rt]||MaxiLen[rt]==r-l+1) 这三种可以合并起来写
代码
/*i.hdu1540*/ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> using namespace std; const int N=2e6+3; int STK[N],HEAD=0;int n,m; int pre[N<<2],last[N<<2],MaxiLen[N<<2]; #define LS (rt<<1) #define RS (LS|1) void build(int rt,int l,int r){ pre[rt]=last[rt]=MaxiLen[rt]=r-l+1; if(l==r)return; int mid=l+r>>1; build(LS,l,mid); build(RS,mid+1,r); } void pushup(int rt,int l,int r){ MaxiLen[rt]=max(max(MaxiLen[LS],MaxiLen[RS]),pre[RS]+last[LS]); int mid=l+r>>1; if(pre[LS]==mid-l+1)pre[rt]=mid-l+1+pre[RS]; else pre[rt]=pre[LS]; if(last[RS]==r-mid)last[rt]=r-mid+last[LS]; else last[rt]=last[RS]; return; } void update(int rt,int l,int r,int x,int p){ if(l==r){pre[rt]=last[rt]=MaxiLen[rt]=p;return;} int mid=l+r>>1; if(x<=mid)update(LS,l,mid,x,p); else update(RS,mid+1,r,x,p); pushup(rt,l,r); } int query(int rt,int l,int r,int x){ if(l==r||!MaxiLen[rt]||MaxiLen[rt]==r-l+1)return MaxiLen[rt]; //找到x ||含x的区间全是0 || 含x的区间全是1 int mid=l+r>>1; if(x<=mid){ if(x>=mid-last[LS]+1)return last[LS]+pre[RS]; //夹中间 else return query(LS,l,mid,x); //LS }else{ if(x<=mid+pre[RS])return last[LS]+pre[RS]; //夹中间 else return query(RS,mid+1,r,x); //RS } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ build(1,1,n); char c=getchar();int x; while(m--){ c=getchar(); if(c=='D'){ scanf("%d",&x); update(1,1,n,x,0); STK[++HEAD]=x; } else if(c=='Q'){ scanf("%d",&x); printf("%d\n",query(1,1,n,x)); } else update(1,1,n,STK[HEAD--],1); c=getchar(); } } return 0; }