HDU 1540 (区间合并)
#include<stdio.h> #include<stdlib.h> #include<string.h> #define maxn 50010 #define Lson root*2 #define Rson root*2+1 #define Max(a,b)(a>b?a:b) int ac[maxn]; struct ndoe {//lsum表示左区间的连续,rsum表示在右区间的连续,sum表示中间区间的连续; int L,R; int lsum,rsum,sum; int Mid() { return (R+L)/2; } int len() { return (R-L+1); } } a[maxn*4]; void BuildTree(int root,int L,int R) { a[root].L=L,a[root].R=R; a[root].lsum = a[root].rsum = a[root].sum = a[root].len(); if(L==R) return ; BuildTree(Lson,L,a[root].Mid()); BuildTree(Rson,a[root].Mid()+1,R); } void pushup(int root) { a[root].lsum = a[Lson].lsum, a[root].rsum = a[Rson].rsum;//左区间的连续 最大为子节点的最大连续,右区间同理; if(a[Lson].lsum == a[Lson].len()) //如果子节点的最大连续等于其长度,则说明其最大连续可以加上右区间的左连续; a[root].lsum = a[Lson].lsum + a[Rson].lsum; if(a[Rson].rsum == a[Rson].len()) a[root].rsum = a[Rson].rsum + a[Lson].rsum; a[root].sum = Max(a[root].lsum, Max(a[root].rsum, a[Lson].rsum+a[Rson].lsum));//中间区间的最大为三个数的最大值(左连续,右连续,子节点左区间的右连续+右区间的左连续) } void update(int root, int k, int e) { if( a[root].L == a[root].R ) { a[root].lsum = a[root].rsum = a[root].sum = e; return ; } if(k <= a[root].Mid()) update(Lson, k, e); else update(Rson, k, e); pushup(root); } int Query(int root,int k) { if(a[root].sum ==0 ) return 0; if(k < a[root].L +a[root].lsum) //判断其是否在左区间;K < 左端点 + 左连续; return a[root].lsum; if(k > a[root].R - a[root].rsum) //判断其是否在右区间; k > 右端点 - 右连续; return a[root].rsum; if(k > (a[Lson].R - a[Lson].rsum) && k < (a[Rson].L + a[Rson].lsum)) //判断是否在中间; 右端点 - 右连续 < K < 左端点 + 左连续; return a[Rson].lsum + a[Lson].rsum; if(k<=a[root].Mid()) return Query(Lson,k); else return Query(Rson,k); } int main() { int n,m,k,w; char str[10]; while(~scanf("%d%d",&n,&m)) { k=0; BuildTree(1,1,n); while(m--) { scanf("%s",str); if(str[0]=='D') { scanf("%d",&w); ac[k]=w; update(1,w,0); k++; } if(str[0]=='R') { k--; w = ac[k]; update(1,w,1); } if(str[0] == 'Q') { scanf("%d",&w); printf("%d\n",Query(1,w)); } } } return 0; }