hdu 1540 Tunnel Warfare 线段树
给你一个01序列,每次将一个位置变成0或1。问某个位置所在的最长1串多长。
我们维护vec[k],k所代表序列中的最长子串长度,ls[k],k所代表序列中的最长前缀,rs[k],k所代表序列中的最长后缀。
合并很简单,vec[k] = max(vec[k << 1],vec[k << 1 | 1],rs[k <<1] + ls[k << 1 | 1]。ls[k] = ls[k << 1] (左半段不都是1) ls[k] = vec[k << 1] + ls[k << 1 | 1](左半段都是1) rs维护同理。
然后考虑查询,最后查询位置所在的最长1串,必定是某个区间的rs和相邻区间的ls拼接起来的。
我们每次看,如果x属于左半段的最大后缀,那么这个最大后缀+右半段最大前缀就是答案。否则递归左子树去找。(x属于左半段)
如果x属于右半段的最大前缀,那么这个最大后缀+右半段最大前缀就是答案。否则递归右子树去找。(x属于右半段)
这题多case,题目没说.....
1 #include <cstdio> 2 #include <stack> 3 using namespace std; 4 stack <int> stk; 5 int vec[210000],ls[210000],rs[210000]; 6 int n,q; 7 void updata(int k,int l,int r) 8 { 9 int mid = l + r >> 1; 10 if (vec[k << 1] == mid - l + 1) 11 ls[k] = vec[k << 1] + ls[k << 1 | 1]; 12 else 13 ls[k] = ls[k << 1]; 14 if (vec[k << 1 | 1] == r - mid) 15 rs[k] = vec[k << 1 | 1] + rs[k << 1]; 16 else 17 rs[k] = rs[k << 1 | 1]; 18 vec[k] = max(rs[k << 1] + ls[k << 1 | 1],max(vec[k << 1],vec[k << 1 | 1])); 19 } 20 void build(int k,int l,int r) 21 { 22 if (l == r) 23 { 24 vec[k] = ls[k] = rs[k] = 1; 25 return; 26 } 27 int mid = l + r >> 1; 28 build(k << 1,l,mid); 29 build(k << 1 | 1,mid + 1,r); 30 updata(k,l,r); 31 } 32 void change(int k,int l,int r,int x,int vl) 33 { 34 if (l == r) 35 { 36 vec[k] = ls[k] = rs[k] = vl; 37 return; 38 } 39 int mid = l + r >> 1; 40 if (x <= mid) change(k << 1,l,mid,x,vl); 41 if (x >= mid + 1) change(k << 1 | 1,mid + 1,r,x,vl); 42 updata(k,l,r); 43 } 44 int query(int k,int l,int r,int x) 45 { 46 if (l == r) 47 return vec[k]; 48 int mid = l + r >> 1; 49 if (x <= mid) 50 { 51 if (x >= (mid - rs[k << 1] + 1)) 52 return rs[k << 1] + ls[k << 1 | 1]; 53 else 54 return query(k << 1,l,mid,x); 55 }else 56 { 57 if (x <= (mid + ls[k << 1 | 1])) 58 return rs[k << 1] + ls[k << 1 | 1]; 59 else 60 return query(k << 1 | 1,mid + 1,r,x); 61 } 62 } 63 int main() 64 { 65 while (scanf("%d%d",&n,&q) > 0) 66 { 67 build(1,1,n); 68 char str[10]; 69 int tx; 70 for (int i = 1;i <= q;i++) 71 { 72 scanf("%s",str); 73 if (str[0] == 'D') 74 { 75 scanf("%d",&tx); 76 change(1,1,n,tx,0); 77 stk.push(tx); 78 }else if (str[0] == 'Q') 79 { 80 scanf("%d",&tx); 81 printf("%d\n",query(1,1,n,tx)); 82 }else 83 { 84 change(1,1,n,stk.top(),1); 85 stk.pop(); 86 } 87 } 88 } 89 return 0; 90 }
心之所动 且就随缘去吧