题目链接:hdu 1540
题目大意:D x 表示x位置被炸毁, R表示修复最近被炸毁的点,Q x 表示查询包括x点在内连续最大的区间并且满足这段中都是没有被炸毁。
代码:
#include<cstdio> #include<algorithm> using namespace std; #define maxn 50000+10 #define lson left, mid, rt<<1 #define rson mid + 1, right, rt<<1|1 int tree[maxn<<2]; int l_max[maxn<<2], r_max[maxn<<2]; void build(int left, int right, int rt) { tree[rt] = l_max[rt] = r_max[rt] = right-left+1; if(left == right) return; int mid = (left + right)>>1; build(left, mid, rt<<1); build(mid + 1, right, (rt<<1)|1); } void pushUp(int rt, int m) { l_max[rt] = l_max[rt<<1]; r_max[rt] = r_max[(rt<<1)|1]; if(l_max[rt] == m-(m>>1)) l_max[rt] += l_max[(rt<<1)|1]; if(r_max[rt] == (m>>1)) r_max[rt] += r_max[rt<<1]; tree[rt] = max(tree[rt<<1], tree[(rt<<1)|1]); tree[rt] = max(tree[rt], r_max[rt<<1] + l_max[(rt<<1)|1] - 1); } void upDate(int pos, int change, int left, int right, int rt) { if(left == right){ tree[rt] = l_max[rt] = r_max[rt] = change? 1:0; return ; } int mid = (left + right)>>1; if(pos <= mid) upDate(pos, change, left, mid, rt<<1); else if(pos > mid) upDate(pos, change, mid + 1, right, (rt<<1)|1); pushUp(rt, right-left+1); } int query(int pos, int left, int right, int rt) { if(left == right || (tree[rt] == 0) || (tree[rt] == right-left+1)){ return tree[rt]; } int mid = (left + right)>>1; if(pos <= mid){ if(pos >= mid- r_max[rt<<1] + 1){ return r_max[rt<<1] + l_max[(rt<<1)|1]; } else return query(pos, left, mid, rt<<1); } else if(pos > mid){ if(pos <= l_max[(rt<<1)|1] + mid){ return r_max[rt<<1] + l_max[(rt<<1)|1]; } else return query(pos, mid + 1, right, (rt<<1)|1); } } int main() { int n, m, p; char op; while(~scanf("%d%d", &n, &m)){ int ss[maxn], cnt = 0; build(1, n, 1); for(int i = 0; i < m; i++){ getchar(); scanf("%c", &op); if(op == 'D'){ scanf("%d", &p); ss[cnt++] = p; upDate(p, 0, 1, n, 1); } else if(op == 'Q'){ scanf("%d", &p); int res = query(p, 1, n, 1); printf("%d\n", res); } else if(op == 'R'){ if(cnt > 0){ p = ss[--cnt]; upDate(p, 1, 1, n, 1); } } } } return 0; } /* 20 100 D 8 D 12 Q 10 */