hdu 1540 Tunnel Warfare

做线段也做了不少题了,想看看自己什么水平,就随便找一道题来做,

谁知,还是不行,最后还是去百度,goole了,看了别人的解题报告才知道自己是多么天真

自己的方法一点好似不靠边,哎~~~~

 

这题说是经典的说,特别是它的查询,觉得如果是自己从一片空白想出来还是真难的说,不过

看别人的代码还是很容易理解的,继续努力!!!!!

关键更新:

tree[k].ml = max(max(tree[L].ml,tree[R].ml),tree[L].rl+tree[R].ll);//当前结点最大长度ml,为左右结点ml及(左结点从右数连续长度+右结点从左数的连续长度)中的最大值 tree[k].ll = tree[L].ll; if(tree[k].ll == mid-tree[k].l) tree[k].ll += tree[R].ll;//当前结点从左数的连续长度 = 左结点从左起的连续长度+(右结点从左起的连续长度(如果左结点全为连续)) tree[k].rl = tree[R].rl; if(tree[k].rl == tree[k].r-mid) tree[k].rl += tree[L].rl;//同上

 

 

完整代码:

#include<stdio.h> #define N 50005 struct node{ int l; int r; int rl; int ll; int ml; void update(int data){ rl = ll = ml = data; } }; node tree[3*N]; int max(int a,int b) { return a > b? a:b; } void buid_tree(int k,int left,int right) { int mid; int L,R; tree[k].l = left; tree[k].r = right; tree[k].ml = tree[k].ll = tree[k].rl = tree[k].r-tree[k].l; if(tree[k].r-tree[k].l == 1) return ; mid = (tree[k].l+tree[k].r)/2; L = 2*k; R = L+1; buid_tree(L,left,mid); buid_tree(R,mid,right); return ; } void tree_insert(int k,int left,int right,int data) { int mid; int L,R; if(left <= tree[k].l && right >= tree[k].r){ tree[k].update(data); return ; } mid = (tree[k].l+tree[k].r)/2; L = k<<1; R = L+1; if(left < mid) tree_insert(L,left,right,data); if(right > mid) tree_insert(R,left,right,data); //关键更新 tree[k].ml = max(max(tree[L].ml,tree[R].ml),tree[L].rl+tree[R].ll);//当前结点最大长度ml,为左右结点ml及(左结点从右数连续长度+右结点从左数的连续长度)中的最大值 tree[k].ll = tree[L].ll; if(tree[k].ll == mid-tree[k].l) tree[k].ll += tree[R].ll;//当前结点从左数的连续长度 = 左结点从左起的连续长度+(右结点从左起的连续长度(如果左结点全为连续)) tree[k].rl = tree[R].rl; if(tree[k].rl == tree[k].r-mid) tree[k].rl += tree[L].rl;//同上 return ; } int tree_search(int k,int left,int right) { int mid; int L,R; if(left <= tree[k].l && right >= tree[k].r || tree[k].ml == tree[k].r-tree[k].l || !tree[k].ml){//当前结点长度为1时,无损时,全损时 return tree[k].ml; } mid = (tree[k].l+tree[k].r)/2; L = k<<1; R = L+1; //查询结点在左结点 if(left < mid){ if(left < mid-tree[L].rl) return tree_search(L,left,right);//如果要查询结点不在左结点从右起连续区间中,继续查询 else return tree[R].ll+tree[L].rl;//如果在其中,则结果 = 左结点从右起连续区间长度+右结点从左起连续区间长度 } if(right > mid){ if(right > mid+tree[R].ll) return tree_search(R,left,right); else return tree[L].rl+tree[R].ll; } return 0; } int main() { int n,m; int x; int i; char ch; int arr[50005]; int top,base; while(scanf("%d %d",&n,&m) == 2){ buid_tree(1,1,n+1); top = base = 0; while(m--){ getchar(); scanf("%c",&ch); if(ch == 'Q'){ scanf("%d",&x); printf("%d/n",tree_search(1,x,x+1)); } if(ch == 'R'){ if(top-base > 0){ tree_insert(1,arr[top-1],arr[top-1]+1,1); top--; } } if(ch == 'D'){ scanf("%d",&x); arr[top] = x; top++; tree_insert(1,x,x+1,0); } } } return 0; }

你可能感兴趣的:(c,struct,百度,tree,search,insert)