hdu 3911 区间合并+区间查询

来源:互联网 发布:火并软件下载 编辑:程序博客网 时间:2024/05/16 01:40

Black And White


Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3638    Accepted Submission(s): 1086


Problem Description
There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she want to know the longest period of consecutive black stones in a range [i, j].
 

Input
  There are multiple cases, the first line of each case is an integer n(1<= n <= 10^5), followed by n integer 1 or 0(1 indicates black stone and 0 indicates white stone), then is an integer M(1<=M<=10^5) followed by M operations formatted as x i j(x = 0 or 1) , x=1 means change the color of stones in range[i,j], and x=0 means ask the longest period of consecutive black stones in range[i,j]
 

Output
When x=0 output a number means the longest length of black stones in range [i,j].
 

Sample Input
41 0 1 050 1 41 2 30 1 41 3 30 4 4
 

Sample Output
120
 

Source
2011 Multi-University Training Contest 8 - Host by HUST

解释在线段树习题集中有,下面贴出代码,如有可以优化的地方希望指正。


#include <cstdio>#include <iostream>#include <queue>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int maxn = 100000+10;int data[maxn];int setv[4*maxn];int lb[4*maxn], rb[4*maxn], sb[4*maxn];int lw[4*maxn], rw[4*maxn], sw[4*maxn];void pushup(int root, int l, int r){  int lc = 2*root, rc = 2*root+1;  int len = r-l+1;  // 处理黑连块  lb[root] = lb[lc];  if(lb[lc] == len-len/2) lb[root] += lb[rc];  rb[root] = rb[rc];  if(rb[root] == len/2) rb[root] += rb[lc];  sb[root] = max(rb[lc]+lb[rc], max(sb[lc], sb[rc]));  // 右孩子的左边,左孩子的右边  // 处理白连块  lw[root] = lw[lc];  if(lw[lc] == len-len/2) lw[root] += lw[rc];  rw[root] = rw[rc];  if(rw[root] == len/2) rw[root] += rw[lc];  sw[root] = max(rw[lc]+lw[rc], max(sw[lc], sw[rc]));}void build(int root, int l, int r){  int mid = (l+r)/2, lc = 2*root, rc = 2*root+1;  if(l < r){    build(lc, l, mid);    build(rc, mid+1, r);    pushup(root, l, r);  }else{    if(data[l] == 1){      lb[root] = rb[root] = sb[root] = 1;      lw[root] = rw[root] = sw[root] = 0;    }else{      lb[root] = rb[root] = sb[root] = 0;      lw[root] = rw[root] = sw[root] = 1;    }  }}void exchange(int root){  swap(lb[root], lw[root]);  swap(rb[root], rw[root]);  swap(sb[root], sw[root]);}void pushdown(int root, int l, int r){  int lc = 2*root, rc = 2*root+1;  if(setv[root]){    setv[lc] ^= 1; setv[rc] ^= 1;    setv[root] = 0;    exchange(lc);  exchange(rc);  }}void modify(int root, int l, int r, int x, int y){  int mid = (l+r)/2, lc = 2*root, rc = 2*root+1;  if(x <= l && r <= y){    setv[root] ^= 1;    exchange(root);  }else{    pushdown(root, l, r);    if(x <= mid) modify(lc, l, mid, x, y);    if(y > mid) modify(rc, mid+1, r, x, y);    pushup(root, l, r);  }}// 区间查询int query(int root, int l, int r, int x, int y){  int mid = (l+r)/2, lc = 2*root, rc = 2*root+1;  if(x <= l && r <= y){    return sb[root];  }else{    pushdown(root, l, r);    int lsum, rsum;    lsum = rsum = 0;    if(y <= mid) return query(lc, l, mid, x, y);    if(x > mid) return query(rc, mid+1, r, x, y);    lsum = query(lc, l, mid, x, y);    // 完全在左子树的    rsum = query(rc, mid+1, r, x, y);    // 完全在右子树的    int len = r-l+1;    int b1 = min(mid-x+1, rb[lc]);    int b2 = min(y-mid, lb[rc]);    // 横跨左右子树的,但是右不能重复计算    return max(max(lsum, rsum), b1+b2);  }}template <class T>inline void Input(T &x){  char c; x = 0;  while((c = getchar()) < '0' || c > '9');  while(c >= '0' && c <= '9') x = x*10 + (c-'0'), c = getchar();}template <class T>inline void Output(T x){  if(x > 9) Output(x/10);  putchar(x%10+'0');}int main(){  int n, m;  while(scanf("%d", &n) != EOF){    memset(setv, 0, sizeof(setv));    for(int i = 1; i <= n; i ++){      //scanf("%d", &data[i]);      Input(data[i]);    }    build(1, 1, n);    int a, b, c;    //scanf("%d", &m);    Input(m);    for(int i = 1; i <= m; i ++){     // scanf("%d%d%d", &a, &b, &c);     Input(a); Input(b); Input(c);      if(a == 0){        int ans = query(1, 1, n, b, c);        //printf("%d\n", ans);         Output(ans);  puts("");      }else{        modify(1, 1, n, b, c);      }    }  }  return 0;}










 
0 0
原创粉丝点击