(i) hdu1540 (区间合并)
Posted lsy263
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(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;
以上是关于(i) hdu1540 (区间合并)的主要内容,如果未能解决你的问题,请参考以下文章
Tunnel Warfare HDU - 1540 (区间合并)
HDU1540 Tunnel Warfare —— 线段树 区间合并
HDU 1540 Tunnel Warfare(线段树 区间合并)