hdu1540/poj2892 线段数区间合并
Posted %%%%%
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu1540/poj2892 线段数区间合并相关的知识,希望对你有一定的参考价值。
题意:n个点,有3种操作D a表示摧毁a这个点,R 表示修复上一个点,Q x表示查询x所在的区间没被摧毁的连续最大区间
思路:线段树区间合并,区间合并主要就是对lsum rsum 和sum的动态维护,注意合并的条件,写的时候主要注意push_up和push_down,还有对于不同的查询query的写法不一样,update和creat和普通的线段树差不多,这里查询x所在区间可行的最大区间,每一个节点(子树)可以知道的连续区间只有lsum[rt],rsum[rt] 和 rsum[lrt]+lsum[rrt] ,所以只能从这3个区间入手,每次判断x是否被某个连续的区间所覆盖即可
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #pragma comment(linker, "/STACK:102400000,102400000") #define ll long long #define endl ("\n") #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ft (frist) #define sd (second) #define lrt (rt<<1) #define rrt (rt<<1|1) #define len (r-l+1) using namespace std; const long long INF = 1e18+1LL; const int inf = 1e9+1e8; const int N=1e5+100; const ll mod=1e9+7; int n,sum[N<<1],lsum[N<<1],rsum[N<<1],lazy[N<<1]; void push_up(int rt, int m){ int rm=m>>1, lm=m-rm; lsum[rt]=lsum[lrt], rsum[rt]=rsum[rrt]; if(lsum[rt]==lm){ lsum[rt]+=lsum[rrt]; } if(rsum[rt]==rm){ rsum[rt]+=rsum[lrt]; } sum[rt]=max(sum[lrt],sum[rrt]); sum[rt]=max(sum[rt],rsum[lrt]+lsum[rrt]); } void push_down(int rt, int m){ int rm=m>>1, lm=m-rm; if(lazy[rt]==0){ lm=rm=0; } sum[lrt]=lsum[lrt]=rsum[lrt]=lm; sum[rrt]=lsum[rrt]=rsum[rrt]=rm; lazy[lrt]=lazy[rrt]=lazy[rt]; lazy[rt]=-1; } void creat(int rt, int l, int r){ if(l==r){ sum[rt]=lsum[rt]=rsum[rt]=1; return; } lazy[rt]=-1; int mid=l+r>>1; creat(lrt,l,mid); creat(rrt,mid+1,r); push_up(rt, len); } void update(int rt, int l, int r, int L, int R, int v){ if(l>=L && r<=R){ int m=len; lazy[rt]=v; if(!v) m=0; //cout<<m<<endl; sum[rt]=lsum[rt]=rsum[rt]=m; return; } if(lazy[rt]!=-1) push_down(rt, len); int mid=l+r>>1; if(L<=mid) update(lrt, l, mid, L, R, v); if(R>mid) update(rrt, mid+1, r, L, R, v); push_up(rt, len); } int query(int rt, int l, int r, int x){ if(l==r) return sum[rt]; if(lazy[rt]!=-1) push_down(rt, len); int mid=l+r>>1; if(lsum[rt]>=x) return lsum[rt]; else if(n-rsum[rt]+1<=x) return rsum[rt]; else if(mid-rsum[lrt]+1<=x && mid+lsum[rrt] >=x ) return rsum[lrt]+lsum[rrt]; else if(x<=mid) return query(lrt, l, mid, x); else return query(rrt, mid+1, r, x); } int main(){ //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); char c; int x,m; while(cin>>n>>m){ creat(1,1,n); int l=0, d[N]; while(m--){ cin>>c; if(c==‘R‘){ x=d[l--]; update(1,1,n,x,x,1); } else{ cin>>x; if(c==‘D‘){ d[++l]=x; update(1,1,n,x,x,0); } else{ cout<<query(1,1,n,x)<<endl; } } } } return 0; }
以上是关于hdu1540/poj2892 线段数区间合并的主要内容,如果未能解决你的问题,请参考以下文章
hdu 1540/POJ 2892 Tunnel Warfare 线段树区间合并