线段树专辑
欢迎大家移步去看这篇写的更详细的文章
这几天陆陆续续更新了下边几道我所能找到得具有一些代表性的线段树题目
从最最简单的区间求和到对区间的各种操作都包涵在这些题目里了
相信对一些准备学习线段树的人有一定得帮助
突然发现自己对数据结构的题目非常有感觉,所以在刷下边的题的同时也生出灵感出了好几道线段树题目
等比赛结束后也会陆续加进里边
快半年过去代码风格也有很大的改变,感觉以前写的代码很不规范,用自己在预定义中定义的一些函数,但后来感觉作用不是很大,所以又删去了,所以现在看代码可能找不到以前我定义的一些函数,本来想更新一下的,无奈这些函数用的太多,改之太过麻烦,所以在此处申明一下
#define LL(x) ((x)<<1)
#define RR(x) ((x)<<1|1)
#define FF(i,n) for(int i = 0 ; i < n ; i ++)
若还有不清楚的地方,只管提出来便是,我一定一一改正
1.hdu1166 敌兵布阵
更新节点,区间求和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | struct Seg_Tree{ int left,right,num; int calmid() { return (left+right)/2; } }tt[150000]; int num[50001]; int build(int left,int right,int idx) { tt[idx].left = left; tt[idx].right = right; if(left == right) { return tt[idx].num = num[left]; } int mid = (left + right)/2; return tt[idx].num = build(left,mid,LL(idx)) + build(mid+1,right,RR(idx)); } void update(int id,int x,int idx) { tt[idx].num += x; if(tt[idx].left == tt[idx].right) { return ; } int mid = tt[idx].calmid(); if(id <= mid) { update(id,x,LL(idx)); } else { update(id,x,RR(idx)); } } int query(int left,int right,int idx) { if(left == tt[idx].left && right == tt[idx].right) { return tt[idx].num; } int mid = tt[idx].calmid(); if(right <= mid) { return query(left,right,LL(idx)); } else if(mid < left) { return query(left,right,RR(idx)); } else { return query(left,mid,LL(idx)) + query(mid+1,right,RR(idx)); } } int main() { int T; scanf(“%d”,T); FF(cas,T) { int n; scanf(“%d”,&n); FOR(i,1,1+n) { scanf(“%d”,num[i]); } build(1,n,1); printf("Case %d:\n",cas+1); char com[9]; while(scanf("%s",com)) { if(strcmp(com,"End") == 0) break; int a,b; scanf("%d%d",&a,&b); switch(com[0]) { case 'Q': printf("%d\n",query(a,b,1)); break; case 'A': update(a,b,1); break; case 'S': update(a,-b,1); break; } } } return 0; } |
.
2.hdu1754 I Hate It
更新节点,区间最值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | struct Seg_Tree { int left,right,val; int calmid() { return (left+right)/2; } }tt[600000]; int val[200001]; int build(int left,int right,int idx) { tt[idx].left = left; tt[idx].right = right; if(left == right) { return tt[idx].val = val[left]; } int mid = tt[idx].calmid(); return tt[idx].val = max(build(left,mid,LL(idx)) , build(mid+1,right,RR(idx))); } void update(int id,int x,int idx) { if(tt[idx].left == tt[idx].right){ tt[idx].val = x; return ; } int mid = tt[idx].calmid(); if(id <= mid) { update(id,x,LL(idx)); } else { update(id,x,RR(idx)); } tt[idx].val = max(tt[LL(idx)].val , tt[RR(idx)].val); } int query(int left,int right,int idx) { if(left == tt[idx].left && right == tt[idx].right) { return tt[idx].val; } int mid = tt[idx].calmid(); if(right <= mid) { return query(left,right,LL(idx)); } else if(mid < left) { return query(left,right,RR(idx)); } else { return max(query(left,mid,LL(idx)) , query(mid+1,right,RR(idx))); } } int main() { int n , m ; while(scanf("%d%d",&n,&m) == 2) { FOR(i,1,n+1) { scanf("%d",&val[i]); } build(1,n,1); while(m --) { char com[2]; int a,b; scanf("%s%d%d",com,&a,&b); if(com[0] == 'Q') { printf("%d\n",query(a,b,1)); } else { update(a,b,1); } } } return 0; } |
.
3.hdu1698 Just a Hook
成段更新,总区间求和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | int n; struct Seg_Tree{ int left,right,col; }tt[300000]; void build(int left,int right,int idx) { tt[idx].left = left; tt[idx].right = right; tt[idx].col = 1; if(left == right) return ; int mid = (left + right)/2; build(left,mid,LL(idx)); build(mid+1,right,RR(idx)); } void update(int left,int right,int col,int idx) { if(left <= tt[idx].left && right >= tt[idx].right) { tt[idx].col = col; return ; } if(tt[idx].col != -1) { tt[LL(idx)].col = tt[RR(idx)].col = tt[idx].col; tt[idx].col = -1; } int mid = (tt[idx].left + tt[idx].right)/2; if(left <= mid) update(left,right,col,LL(idx)); if(mid < right) update(left,right,col,RR(idx)); } int query(int left,int right,int idx) { if(left == tt[idx].left && right == tt[idx].right) { if(tt[idx].col != -1) { return (right - left + 1) * tt[idx].col; } else { int mid = (tt[idx].left + tt[idx].right)/2; return query(left,mid,LL(idx)) + query(mid+1,right,RR(idx)); } } int mid = (tt[idx].left + tt[idx].right)/2; if(right <= mid) { return query(left,right,LL(idx)); } else if(left > mid) { return query(left,right,RR(idx)); } else { return query(left,mid,LL(idx)) + query(mid+1,right,RR(idx)); } } int main() { int T; scanf("%d",&T); FF(cas,T) { int n , m ; scanf("%d",&n); build(1,n,1); scanf("%d",&m); while(m --) { int left,right,col; scanf("%d%d%d",&left,&right,&col); update(left,right,col,1); } printf("Case %d: The total value of the hook is %d.\n",cas+1,query(1,n,1)); } return 0; } |
.
4.hdu1394 Minimum Inversion Number
更新节点,区间求和(实现nlog(n)的逆序数方法,和树状数组比起来实在是有点鸡肋)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | struct Seg_Tree { int left,right,val; int calmid() { return (left+right)/2; } }tt[15000]; int val[5001]; void build(int left,int right,int idx) { tt[idx].left = left; tt[idx].right = right; tt[idx].val = 0; if(left == right) { return ; } int mid = tt[idx].calmid(); build(left,mid,LL(idx)); build(mid+1,right,RR(idx)); } int query(int left,int right,int idx) { if(left == tt[idx].left && right == tt[idx].right) { return tt[idx].val; } int mid = tt[idx].calmid(); if(right <= mid) { return query(left,right,LL(idx)); } else if(mid < left) { return query(left,right,RR(idx)); } else { return query(left,mid,LL(idx)) + query(mid+1,right,RR(idx)); } } void update(int id,int idx) { tt[idx].val ++; if(tt[idx].left == tt[idx].right) { return ; } int mid = tt[idx].calmid(); if(id <= mid) { update(id,LL(idx)); } else { update(id,RR(idx)); } } int main() { int n; while(scanf("%d",&n) == 1) { build(0,n-1,1); int sum = 0; FF(i,n) { scanf(“%d”,&val[i]); sum += query(val[i],n-1,1); update(val[i],1); } int ret = sum; FF(i,n) { sum = sum - val[i] + (n - val[i] - 1); checkmin(ret,sum); } printf("%d\n",ret); } return 0; } |
.
5.hdu1779 9-Problem C暂不公开
成段更新,区间最值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | struct Node{ int idx; int val; friend bool operator < (Node a,Node b) { if(a.val == b.val) { return a.idx > b.idx; } return a.val < b.val; } }; struct Seg_Tree { int left,right; Node node; int add; int calmid() { return (left+right)/2; } }tt[300000]; void build(int left,int right,int idx) { tt[idx].left = left; tt[idx].right = right; tt[idx].add = 0; tt[idx].node.idx = left; tt[idx].node.val = 0; if(left == right) { return ; } int mid = tt[idx].calmid(); build(left,mid,LL(idx)); build(mid+1,right,RR(idx)); } void update(int left,int right,int add,int idx) { if(left <= tt[idx].left && right >= tt[idx].right) { tt[idx].node.val += add; tt[idx].add += add; return ; } if(tt[idx].add) { tt[LL(idx)].node.val += tt[idx].add; tt[RR(idx)].node.val += tt[idx].add; tt[LL(idx)].add += tt[idx].add; tt[RR(idx)].add += tt[idx].add; tt[idx].add = 0; } int mid = tt[idx].calmid(); if(left <= mid) update(left,right,add,LL(idx)); if(mid < right) update(left,right,add,RR(idx)); tt[idx].node = max(tt[LL(idx)].node , tt[RR(idx)].node); } Node query(int left,int right,int idx) { if(left == tt[idx].left && right == tt[idx].right) { return tt[idx].node; } if(tt[idx].add) { tt[LL(idx)].node.val += tt[idx].add; tt[RR(idx)].node.val += tt[idx].add; tt[LL(idx)].add += tt[idx].add; tt[RR(idx)].add += tt[idx].add; tt[idx].add = 0; } int mid = tt[idx].calmid(); if(right <= mid) { return query(left,right,LL(idx)); } else if(left > mid) { return query(left,right,RR(idx)); } else { return max(query(left,mid,LL(idx)) , query(mid+1,right,RR(idx))); } } int main() { int n , m ; while(scanf("%d%d",&n,&m) == 2) { if(n == 0 && m == 0) break; build(1,n,1); while(m --) { char com[2]; scanf("%s",&com); if(com[0] == 'I') { int a,b,c; scanf("%d%d%d",&a,&b,&c); update(a,b,c,1); } else { int a,b; scanf("%d%d",&a,&b); Node ret = query(a,b,1); printf("%d\n",ret.val); update(ret.idx,ret.idx,-ret.val,1); } } } return 0; } |
.
6.pku2777 Count Color
成段更新,区间统计,位运算加速(我总把query里的传递给子节点的步骤忘了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | template<class T> inline T countbit(T n) {return n?1+countbit(n&(n-1)):0;} #define two(x) ((LL)1<<(x)) struct Seg_Tree{ int left,right; int col; bool cover; int calmid() { return (left+right)/2; } }tt[300000]; void build(int left,int right,int idx) { tt[idx].left = left; tt[idx].right = right; tt[idx].col = two(1); tt[idx].cover = true; if(left == right) { return ; } int mid = tt[idx].calmid(); build(left,mid,LL(idx)); build(mid+1,right,RR(idx)); } void update(int left,int right,int c,int idx) { if(left <= tt[idx].left && right >= tt[idx].right) { tt[idx].cover = true; tt[idx].col = two(c); return ; } if(tt[idx].cover) { tt[RR(idx)].col = tt[LL(idx)].col = tt[idx].col; tt[RR(idx)].cover = tt[LL(idx)].cover = true; tt[idx].cover = false; } int mid = tt[idx].calmid(); if(left <= mid) update(left,right,c,LL(idx)); if(mid < right) update(left,right,c,RR(idx)); tt[idx].col = tt[LL(idx)].col | tt[RR(idx)].col; } int query(int left,int right,int idx) { if(left == tt[idx].left && right == tt[idx].right) { return tt[idx].col; } if(tt[idx].cover) { tt[RR(idx)].col = tt[LL(idx)].col = tt[idx].col; tt[RR(idx)].cover = tt[LL(idx)].cover = true; tt[idx].cover = false; } int mid = tt[idx].calmid(); if(right <= mid) { return query(left,right,LL(idx)); } else if(mid < left) { return query(left,right,RR(idx)); } else { return query(left,mid,LL(idx)) | query(mid+1,right,RR(idx)); } } int main() { int n,T,o; while(scanf("%d%d%d",&n,&T,&o) == 3) { build(1,n,1); while(o--) { char ch[2]; scanf("%s",&ch); if(ch[0] == 'C') { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a > b) swap(a,b); update(a,b,c,1); } else { int a,b; scanf("%d%d",&a,&b); if(a > b) swap(a,b); printf("%d\n",countbit(query(a,b,1))); } } } return 0; } |
.
7.pku3468 A Simple Problem with Integers
成段更新,区间求和(中间乘法会超int..纠结了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | struct Seg_Tree{ int left,right; LL sum; int add; int calmid() { return (left+right)/2; } int caldis() { return right - left + 1; } }tt[400000]; int val[100001]; LL build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].add = 0; if(l == r) { return tt[idx].sum = val[l]; } int mid = tt[idx].calmid(); return tt[idx].sum = build(l,mid,LL(idx)) + build(mid+1,r,RR(idx)); } void update(int l,int r,int add,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].add += add; tt[idx].sum += (LL)tt[idx].caldis() * add; return ; } if(tt[idx].add) { tt[LL(idx)].sum += (LL)tt[LL(idx)].caldis() * tt[idx].add; tt[RR(idx)].sum += (LL)tt[RR(idx)].caldis() * tt[idx].add; tt[LL(idx)].add += tt[idx].add; tt[RR(idx)].add += tt[idx].add; tt[idx].add = 0; } int mid = tt[idx].calmid(); if(l <= mid) update(l,r,add,LL(idx)); if(mid < r) update(l,r,add,RR(idx)); tt[idx].sum = tt[LL(idx)].sum + tt[RR(idx)].sum; } LL query(int l,int r,int idx) { if(l == tt[idx].left && r == tt[idx].right) { return tt[idx].sum; } if(tt[idx].add) { tt[LL(idx)].sum += (LL)tt[LL(idx)].caldis() * tt[idx].add; tt[RR(idx)].sum += (LL)tt[RR(idx)].caldis() * tt[idx].add; tt[LL(idx)].add += tt[idx].add; tt[RR(idx)].add += tt[idx].add; tt[idx].add = 0; } int mid = tt[idx].calmid(); if(r <= mid) { return query(l,r,LL(idx)); } else if(mid < l) { return query(l,r,RR(idx)); } else { return query(l,mid,LL(idx)) + query(mid+1,r,RR(idx)); } } int main() { int n , m ; while(scanf("%d%d",&n,&m) == 2) { FOR(i,1,n+1) { scanf("%d",&val[i]); } build(1,n,1); while(m --) { char com[2]; scanf("%s",com); if(com[0] == 'Q') { int a,b; scanf("%d%d",&a,&b); printf("%lld\n",query(a,b,1)); } else { int a,b,c; scanf("%d%d%d",&a,&b,&c); update(a,b,c,1); } } } return 0; } |
.
8.pku2528 Mayor’s posters
成段更新,区间统计(离散化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | struct Seg_Tree{ int left; int right; int col; int mid() { return (left+right)>>1; } }tt[66666]; struct H{ int left,right; }hh[10001]; int pos[20001]; bool hash[10001]; int n , m ,ans ; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].col = -1; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int col,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].col = col; return ; } if(tt[idx].col != -1) { tt[LL(idx)].col = tt[RR(idx)].col = tt[idx].col; tt[idx].col = -1; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,col,LL(idx)); if(mid < r) update(l,r,col,RR(idx)); } void query(int l,int r,int idx) { if(tt[idx].col != -1) { if(!hash[tt[idx].col]) { ans ++; hash[tt[idx].col] = true; } return ; } int mid = tt[idx].mid(); if(r <= mid) { query(l,r,LL(idx)); } else if(mid < l) { query(l,r,RR(idx)); } else { query(l,mid,LL(idx)); query(mid+1,r,RR(idx)); } } int Bin(int x) { int lo = 0; int hi = m-1; while(lo <= hi) { int mid = (lo + hi) >> 1; if(pos[mid] == x) { return mid; } if(pos[mid] < x) { lo = mid + 1; } else { hi = mid - 1; } } return -1; } int main() { int T; scanf("%d",&T); while(T --) { scanf("%d",&n); FF(i,n) { scanf("%d%d",&hh[i].left,&hh[i].right); pos[LL(i)] = hh[i].left; pos[RR(i)] = hh[i].right; } sort(pos,pos+2*n); m = 0; FF(i,2*n) { if(i == 0 || pos[i] != pos[i-1]) { pos[m++] = pos[i]; } } build(0,m-1,1); FF(i,n) { update(Bin(hh[i].left),Bin(hh[i].right),i,1); } ans = 0; CC(hash,false); query(0,m-1,1); printf("%d\n",ans); } return 0; } |
.
9.hdu2795 Billboard
更新节点,询问特殊(暑假的时候不会线段树被这水题狂虐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | struct Node { int val; int idx; friend bool operator < (Node a , Node b) { if(a.val == b.val) { return a.idx > b.idx; } return a.val < b.val; } }error; struct Seg_Tree{ int left,right; Node node; int mid() { return (left + right)>>1; } }tt[800000]; int n , h , m; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].node.idx = l; tt[idx].node.val = h; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int val,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].node.val += val; return ; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,val,LL(idx)); if(mid < r) update(l,r,val,RR(idx)); tt[idx].node = max(tt[LL(idx)].node,tt[RR(idx)].node); } Node query(int w,int idx) { if(tt[idx].node.val < w) { return error; } if(tt[idx].left == tt[idx].right) { return tt[idx].node; } if(tt[LL(idx)].node.val >= w) { return query(w,LL(idx)); } else { return query(w,RR(idx)); } } int main() { error.idx = -1; while(scanf("%d%d%d",&n,&h,&m) == 3) { checkmin(n,m); build(1,n,1); while(m --) { int w; scanf("%d",&w); Node ret = query(w,1); printf("%d\n",ret.idx); if(ret.idx != -1) { update(ret.idx,ret.idx,-w,1); } } } return 0; } |
.
10.pku3667 Hotel
成段更新,寻找空间(经典类型,求一块满足条件的最左边的空间)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | struct Seg_Tree{ int left,right; int cval,lval,rval; int st; int mid() { return (left+right)>>1; } void doit() { cval = lval = rval = st ? 0 : dis(); } int dis() { return (right - left + 1); } }tt[150000]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].st = -1; tt[idx].cval = tt[idx].lval = tt[idx].rval = tt[idx].dis(); if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int st,int idx) { if(tt[idx].left >= l && r >= tt[idx].right) { tt[idx].st = st; tt[idx].doit(); return ; } if(tt[idx].st != -1) { tt[LL(idx)].st = tt[RR(idx)].st = tt[idx].st; tt[LL(idx)].doit(); tt[RR(idx)].doit(); tt[idx].st = -1; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,st,LL(idx)); if(mid < r) update(l,r,st,RR(idx)); tt[idx].cval = max( tt[LL(idx)].rval + tt[RR(idx)].lval , max(tt[LL(idx)].cval,tt[RR(idx)].cval) ); tt[idx].lval = tt[LL(idx)].lval; tt[idx].rval = tt[RR(idx)].rval; if(tt[LL(idx)].cval == tt[LL(idx)].dis()) { tt[idx].lval += tt[RR(idx)].lval; } if(tt[RR(idx)].cval == tt[RR(idx)].dis()) { tt[idx].rval += tt[LL(idx)].rval; } } int query(int w,int idx) { if(tt[idx].left == tt[idx].right && w == 1) { return tt[idx].left; } if(tt[idx].st != -1) { tt[LL(idx)].st = tt[RR(idx)].st = tt[idx].st; tt[LL(idx)].doit(); tt[RR(idx)].doit(); tt[idx].st = -1; } if(tt[LL(idx)].cval >= w) { return query(w,LL(idx)); } else if(tt[LL(idx)].rval + tt[RR(idx)].lval >= w) { return tt[LL(idx)].right - tt[LL(idx)].rval + 1; } else if(tt[RR(idx)].cval >= w){ return query(w,RR(idx)); } else { return 0; } } int main() { int n , m; while(scanf("%d%d",&n,&m) == 2) { build(1,n,1); while(m --) { int com; scanf("%d",&com); if(com == 1) { int a; scanf("%d",&a); int s = query(a,1); printf("%d\n",s); if(s) { update(s,s+a-1,1,1); } } else { int a,b; scanf("%d%d",&a,&b); update(a,a+b-1,0,1); } } } return 0; } |
.
11.hdu1540 Tunnel Warfare
更新节点,询问节点所在区间(同上一道Hotel一样类型的题目)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | struct Seg_Tree{ int left,right; int cval,lval,rval; int mid() { return (left+right)>>1; } void doit(int st) { cval = lval = rval = st ? 0 : dis(); } int dis() { return (right - left + 1); } }tt[150000]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].cval = tt[idx].lval = tt[idx].rval = tt[idx].dis(); if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int id,int st,int idx) { if(tt[idx].left == tt[idx].right) { tt[idx].doit(st); return ; } int mid = tt[idx].mid(); if(id <= mid) { update(id,st,LL(idx)); } else { update(id,st,RR(idx)); } int l = LL(idx); int r = RR(idx); tt[idx].cval = max(tt[l].rval + tt[r].lval , max(tt[l].cval , tt[r].cval)); tt[idx].lval = tt[l].lval; tt[idx].rval = tt[r].rval; if(tt[l].cval == tt[l].dis()) { tt[idx].lval += tt[r].lval; } if(tt[r].cval == tt[r].dis()) { tt[idx].rval += tt[l].rval; } } int query(int id,int idx) { if(tt[idx].left == tt[idx].right || tt[idx].cval == 0 || tt[idx].cval == tt[idx].dis()) { return tt[idx].cval; } int mid = tt[idx].mid(); if(id <= mid) { if(id > tt[LL(idx)].right - tt[LL(idx)].rval) { return query(id,LL(idx)) + query(tt[RR(idx)].left,RR(idx)); } else { return query(id,LL(idx)); } } else { if(id < tt[RR(idx)].left + tt[RR(idx)].lval) { return query(tt[LL(idx)].right,LL(idx)) + query(id,RR(idx)); } else { return query(id,RR(idx)); } } } stack <int> ss; int main() { int n , m ; while(scanf("%d%d",&n,&m) == 2) { build(1,n,1); while(m --) { char com[2]; scanf("%s",com); if(com[0] == 'D') { int idx; scanf("%d",&idx); ss.push(idx); update(idx,1,1); } else if(com[0] == 'Q') { int idx; scanf("%d",&idx); printf("%d\n",query(idx,1)); } else { if(ss.empty()) continue; update(ss.top(),0,1); ss.pop(); } } } return 0; } |
.
12.hdu2871 Memory Control
hotel变形题目,三个都函数一样(vector忘记清空检查了好久)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | struct Seg_Tree{ int left,right; int cval,lval,rval; int st; int mid() { return (left+right)>>1; } void doit() { cval = lval = rval = st ? 0 : dis(); } int dis() { return (right - left + 1); } }tt[150000]; struct Block{ int start; int end; }; vector <Block> hh; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].cval = tt[idx].lval = tt[idx].rval = tt[idx].dis(); tt[idx].st = -1; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int st,int idx) { if(tt[idx].left >= l && r >= tt[idx].right) { tt[idx].st = st; tt[idx].doit(); return ; } if(tt[idx].st != -1) { tt[LL(idx)].st = tt[RR(idx)].st = tt[idx].st; tt[LL(idx)].doit(); tt[RR(idx)].doit(); tt[idx].st = -1; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,st,LL(idx)); if(mid < r) update(l,r,st,RR(idx)); tt[idx].cval = max( tt[LL(idx)].rval + tt[RR(idx)].lval , max(tt[LL(idx)].cval,tt[RR(idx)].cval) ); tt[idx].lval = tt[LL(idx)].lval; tt[idx].rval = tt[RR(idx)].rval; if(tt[LL(idx)].cval == tt[LL(idx)].dis()) { tt[idx].lval += tt[RR(idx)].lval; } if(tt[RR(idx)].cval == tt[RR(idx)].dis()) { tt[idx].rval += tt[LL(idx)].rval; } } int query(int w,int idx) { if(tt[idx].left == tt[idx].right) { if(tt[idx].cval == w) { return tt[idx].left; } else { return 0; } } if(tt[idx].st != -1) { tt[LL(idx)].st = tt[RR(idx)].st = tt[idx].st; tt[LL(idx)].doit(); tt[RR(idx)].doit(); tt[idx].st = -1; } if(tt[LL(idx)].cval >= w) { return query(w,LL(idx)); } else if(tt[LL(idx)].rval + tt[RR(idx)].lval >= w) { return tt[LL(idx)].right - tt[LL(idx)].rval + 1; } else if(tt[RR(idx)].cval >= w){ return query(w,RR(idx)); } else { return 0; } } int Bin(int x) { int lo = 0; int hi = sz(hh) - 1; while(lo <= hi) { int mid = (lo + hi) >> 1; if(hh[mid].start <= x) { lo = mid + 1; } else { hi = mid - 1; } } return lo; } int main() { int n , m ; while(scanf("%d%d",&n,&m) == 2) { build(1,n,1); hh.clear(); while(m --) { char com[9]; scanf("%s",com); if(strcmp(com,"Reset") == 0) { update(1,n,0,1); hh.clear(); puts("Reset Now"); } else if(strcmp(com,"Free") == 0) { int idx; scanf("%d",&idx); int id = Bin(idx) - 1; if(id == -1 || hh[id].end < idx) { puts("Reject Free"); } else { printf("Free from %d to %d\n",hh[id].start,hh[id].end); update(hh[id].start,hh[id].end,0,1); hh.erase(hh.begin()+id,hh.begin()+id+1); } } else if(strcmp(com,"New") == 0) { int w; scanf("%d",&w); if(tt[1].cval < w) { puts("Reject New"); } else { Block buf; buf.start = query(w,1); buf.end = buf.start + w - 1; int idx = Bin(buf.start); hh.insert(hh.begin()+idx,buf); update(buf.start,buf.end,1,1); printf("New at %d\n",buf.start); } } else { int idx; scanf("%d",&idx); idx --; if(idx >= sz(hh)) { puts("Reject Get"); } else { printf("Get at %d\n",hh[idx].start); } } } puts(""); } return 0; } |
.
13.hdu3016 Man Down
成段更新,单点查询(简单线段树+简单DP)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #define mix -2 struct Seg_Tree{ int left; int right; int id; int mid() { return (left + right)>>1; } }tt[400000]; struct H{ int left; int right; int xl,xr,val,h; }hh[100001]; int n; bool cmp(H a,H b) { return a.h < b.h; } void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].id = -1; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int id,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].id = id; return ; } if(tt[idx].id != mix) { tt[LL(idx)].id = tt[RR(idx)].id = tt[idx].id; tt[idx].id = mix; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,id,LL(idx)); if(mid < r) update(l,r,id,RR(idx)); } int query(int pos,int idx) { if(tt[idx].id != mix) { return tt[idx].id; } if(tt[idx].id != mix) { tt[LL(idx)].id = tt[RR(idx)].id = tt[idx].id; tt[idx].id = mix; } int mid = tt[idx].mid(); if(pos <= mid) { return query(pos,LL(idx)); } else { return query(pos,RR(idx)); } } int dp[100001]; int main() { while(scanf("%d",&n) == 1) { FF(i,n) { scanf("%d%d%d%d",&hh[i].h,&hh[i].xl,&hh[i].xr,&hh[i].val); } sort(hh,hh+n,cmp); build(1,100000,1); FF(i,n) { hh[i].left = query(hh[i].xl,1); hh[i].right = query(hh[i].xr,1); update(hh[i].xl,hh[i].xr,i,1); } int ret = -1; CC(dp,-1); dp[n-1] = 100; FFD(i,n) { if(dp[i] == -1) continue; if(hh[i].left == -1) { checkmax(ret,dp[i] + hh[i].val); } else { checkmax(dp[hh[i].left] , dp[i] + hh[i].val); } if(hh[i].right == -1) { checkmax(ret,dp[i] + hh[i].val); } else { checkmax(dp[hh[i].right] , dp[i] + hh[i].val); } } printf("%d\n",ret); } return 0; } |
.
14.hdu1542 Atlantis
矩形面积并,扫描线法(发现我们HDU的队员的矩形面积交模板基本都是在最坏情况下更新到底,宁波惨痛的教训啊..)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | struct Seg_Tree{ int left,right; int cnt; double sum; int mid() { return (left + right) >> 1; } }tt[6666]; struct Seg{ double high; double left,right; int side; }ss[2222]; bool cmp(Seg &a, Seg &b) { return a.high < b.high; } double pos[2222]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].cnt = 0; tt[idx].sum = 0; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int idx) { if(tt[idx].cnt) { tt[idx].sum = pos[tt[idx].right+1] - pos[tt[idx].left]; } else if(tt[idx].left == tt[idx].right) { tt[idx].sum = 0; } else { tt[idx].sum = tt[LL(idx)].sum + tt[RR(idx)].sum; } } void update(int l,int r,int st,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].cnt += st; update(idx); return ; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,st,LL(idx)); if(mid < r) update(l,r,st,RR(idx)); update(idx); } int Bin(double x,int hi) { int lo = 0; while(lo <= hi) { int mid = (lo + hi) >> 1; if(pos[mid] == x) return mid; if(pos[mid] < x) { lo = mid + 1; } else { hi = mid - 1; } } return -1; } int main() { int n; int cas = 1; while(scanf("%d",&n) == 1) { if(n == 0) break; int m = 0; FF(i,n) { double a,b,c,d; scanf("%lf%lf%lf%lf",&a,&b,&c,&d); pos[m] = ss[m].left = ss[m+1].left = a; ss[m].high = b; pos[m+1] = ss[m].right = ss[m+1].right = c; ss[m+1].high = d; ss[m].side = 1; ss[m+1].side = -1; m += 2; } sort(ss,ss+m,cmp); sort(pos,pos+m); int k = 0; FF(i,m) { if(i == 0 || pos[i] != pos[i-1]) { pos[k++] = pos[i]; } } build(0,k-1,1); double ret = 0; FF(i,m-1) { int l = Bin(ss[i].left,k-1); int r = Bin(ss[i].right,k-1) - 1; if(l > r) { ret += tt[1].sum * (ss[i+1].high - ss[i].high); continue; } update(l,r,ss[i].side,1); ret += tt[1].sum * (ss[i+1].high - ss[i].high); } printf("Test case #%d\n",cas++); printf("Total explored area: %.2lf\n\n",ret); } return 0; } |
.
15.hdu1255 覆盖的面积
同上,扫描线法,我多加了一个系数csum,来统计覆盖两次的长度(156MS,第一次做线段树排到第一,纪念下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | struct Seg_Tree{ int left,right; double sum; double csum; int cnt; int mid() { return (left + right) >> 1; } }tt[6000]; struct Seg{ double left,right,high; int side; }ss[2001]; int k; double pos[2001]; bool cmp(Seg &a,Seg &b) { return a.high < b.high; } void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].sum = 0; tt[idx].csum = 0; tt[idx].cnt = 0; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int idx) { if(tt[idx].cnt > 0) { tt[idx].sum = pos[tt[idx].right + 1] - pos[tt[idx].left]; } else if(tt[idx].left == tt[idx].right) { tt[idx].sum = 0; } else { tt[idx].sum = tt[LL(idx)].sum + tt[RR(idx)].sum; } if(tt[idx].cnt > 1) { tt[idx].csum = pos[tt[idx].right + 1] - pos[tt[idx].left]; } else if(tt[idx].left == tt[idx].right) { tt[idx].csum = 0; } else if(tt[idx].cnt > 0) { tt[idx].csum = tt[LL(idx)].sum + tt[RR(idx)].sum; } else { tt[idx].csum = tt[LL(idx)].csum + tt[RR(idx)].csum; } } void update(int l,int r,int st,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].cnt += st; update(idx); return ; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,st,LL(idx)); if(mid < r) update(l,r,st,RR(idx)); update(idx); } int Bin(double x) { int hi = k - 1; int lo = 0; while(lo <= hi) { int mid = (lo + hi) >> 1; if(pos[mid] == x) { return mid; } if(pos[mid] < x) { lo = mid + 1; } else { hi = mid - 1; } } return -1; } int main() { int T; scanf("%d",&T); while(T --) { int n; scanf("%d",&n); int m = 0; FF(i,n) { double a,b,c,d; scanf("%lf%lf%lf%lf",&a,&b,&c,&d); pos[m] = ss[m].left = ss[m+1].left = a; ss[m].high = b; pos[m+1] = ss[m].right = ss[m+1].right = c; ss[m+1].high = d; ss[m].side = 1; ss[m+1].side = -1; m += 2; } sort(ss,ss+m,cmp); sort(pos,pos+m); k = 0; FF(i,m) { if(i == 0 || pos[i] != pos[i-1]) { pos[k++] = pos[i]; } } build(0,k-1,1); double ans = 0; FF(i,m-1) { if(ss[i].left == ss[i].right) { ans += tt[1].sum * (ss[i+1].high - ss[i].high); continue; } int l = Bin(ss[i].left); int r = Bin(ss[i].right) - 1; update(l,r,ss[i].side,1); ans += tt[1].csum * (ss[i+1].high - ss[i].high); } printf("%.2lf\n",ans); } return 0; } |
.
16.hdu1828 Picture
扫描线,同面积统计,加了一个num_Seg统计一个扫描区域里的边
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | struct Seg_Tree{ int left,right; int lbd,rbd; int cnt; int Len; int num_Seg; int mid() { return (left + right) >> 1; } }tt[66666]; struct Seg{ int left; int right; int high; int side; }ss[10001]; bool cmp(Seg &a,Seg &b) { return a.high < b.high; } void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].cnt = tt[idx].Len = tt[idx].num_Seg = 0; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int idx) { if(tt[idx].cnt) { tt[idx].lbd = tt[idx].rbd = 1; tt[idx].Len = tt[idx].right - tt[idx].left + 1; tt[idx].num_Seg = 2; } else if(tt[idx].left == tt[idx].right) { tt[idx].lbd = tt[idx].rbd = 0; tt[idx].Len = 0; tt[idx].num_Seg = 0; } else { int l = LL(idx); int r = RR(idx); tt[idx].lbd = tt[l].lbd; tt[idx].rbd = tt[r].rbd; tt[idx].Len = tt[l].Len + tt[r].Len; tt[idx].num_Seg = tt[l].num_Seg + tt[r].num_Seg - 2 * (tt[l].rbd & tt[r].lbd); } } void update(int l,int r,int st,int idx) { if(tt[idx].left >= l && tt[idx].right <= r) { tt[idx].cnt += st; update(idx); return ; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,st,LL(idx)); if(mid < r) update(l,r,st,RR(idx)); update(idx); } int main() { int n; while(scanf("%d",&n) == 1) { if(n == 0) { puts("0"); continue; } int lup = 10000; int rup = -10000; int m = 0; FF(i,n) { scanf("%d%d%d%d",&ss[m].left,&ss[m].high,&ss[m].right,&ss[m+1].high); ss[m+1].left = ss[m].left; ss[m+1].right = ss[m].right;; ss[m].side = 1; ss[m+1].side = -1; lup = min(lup,ss[m].left); rup = max(rup,ss[m].right); m += 2; } sort(ss,ss+m,cmp); build(lup,rup-1,1); int ans = 0; int buf = 0; ss[m] = ss[m-1]; FF(i,m) { if(ss[i].left != ss[i].right) { update(ss[i].left,ss[i].right-1,ss[i].side,1); } ans += tt[1].num_Seg * (ss[i+1].high - ss[i].high); ans += abs(tt[1].Len - buf); buf = tt[1].Len; } printf("%d\n",ans); } return 0; } |
.
17.pku1436 Horizontally Visible Segments
成段更新,成段询问(染色问题,坐标*2后很简单,最后统计用暴力- -)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | struct Seg_Tree{ int left,right; int col; int mid() { return (left + right) >> 1; } }tt[80000]; #define mix -1 struct Seg{ int pos,left,right; }hh[8888]; vector <int> edge[8888]; int hash[8888]; int cnt[8888]; bool cmp(Seg &a,Seg &b) { return a.pos < b.pos; } void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].col = mix; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int id,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].col = id; return ; } if(tt[idx].col != mix) { tt[LL(idx)].col = tt[RR(idx)].col = tt[idx].col; tt[idx].col = mix; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,id,LL(idx)); if(mid < r) update(l,r,id,RR(idx)); } void query(int l,int r,int id,int idx) { if(tt[idx].col != mix) { if(hash[tt[idx].col] != id) { edge[tt[idx].col].push_back(id); hash[tt[idx].col] = id; } return ; } if(tt[idx].left == tt[idx].right) return ; if(tt[idx].col != mix) { tt[LL(idx)].col = tt[RR(idx)].col = tt[idx].col; tt[idx].col = mix; } int mid = tt[idx].mid(); if(r <= mid) { query(l,r,id,LL(idx)); } else if(mid < l) { query(l,r,id,RR(idx)); } else { query(l,mid,id,LL(idx)); query(mid+1,r,id,RR(idx)); } } int main() { int T; scanf("%d",&T); while(T --) { int n; build(0,16000,1); scanf("%d",&n); FF(i,n) { scanf("%d%d%d",&hh[i].left,&hh[i].right,&hh[i].pos); hh[i].left *= 2; hh[i].right *= 2; edge[i].clear(); } sort(hh,hh+n,cmp); CC(hash,-1); FF(i,n) { query(hh[i].left,hh[i].right,i,1); update(hh[i].left,hh[i].right,i,1); } int ans = 0; FF(i,n) { int m = sz(edge[i]); FF(j,m) { int idx = edge[i][j]; int mm = sz(edge[idx]); FF(k,m) { FF(l,mm) { if(edge[i][k] == edge[idx][l]) { ans ++; } } } } } printf("%d\n",ans); } return 0; } |
.
18.pku3225 Help with Intervals
成段更新,总询问区间(有个异或操作比较新颖)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | #define mix -1 struct Seg_Tree{ int left; int right; int cover; int change; int mid() { return (left + right) >> 1; } void Change() { if(change) { change = 0; } else if(cover != mix) { cover ^= 1; } else { change = 1; } } }tt[800000]; bool hash[131072]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].cover = 0; tt[idx].change = 0; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void Scanf(int &a,int &b,char str[]) { int pos = 1; while(isdigit(str[pos])) { a = a * 10 + str[pos] - '0'; pos ++; } pos ++; while(isdigit(str[pos])) { b = b * 10 + str[pos] - '0'; pos ++; } if(str[0] == '(') { a = a * 2 + 1; } else { a = a * 2; } if(str[pos] == ')') { b = b * 2 - 1; } else { b = b * 2; } } void Printf(int a,int b) { if(a%2 == 0) { printf("[%d,",a/2); } else { printf("(%d,",a/2); } if(b%2 == 0) { printf("%d]",b/2); } else { printf("%d)",b/2+1); } } void update(int l,int r,char op,int idx) { int mid; switch(op) { case 'U': if(l == tt[idx].left && r == tt[idx].right) { tt[idx].cover = 1; tt[idx].change = false; return ; } if(tt[idx].cover != mix) { tt[LL(idx)].cover = tt[RR(idx)].cover = tt[idx].cover; tt[LL(idx)].change = tt[RR(idx)].change = 0; tt[idx].cover = mix; } break; case 'I': if(l == tt[idx].left && r == tt[idx].right) { return ; } if(tt[idx].cover != mix) { tt[LL(idx)].cover = tt[RR(idx)].cover = tt[idx].cover; tt[LL(idx)].change = tt[RR(idx)].change = 0; tt[idx].cover = mix; } mid = tt[idx].mid(); if(r <= mid) tt[RR(idx)].cover = tt[idx].change; if(mid < l) tt[LL(idx)].cover = tt[idx].change; break; case 'D': if(l == tt[idx].left && r == tt[idx].right) { tt[idx].cover = 0; tt[idx].change = false; return ; } if(tt[idx].cover != mix) { tt[LL(idx)].cover = tt[RR(idx)].cover = tt[idx].cover; tt[LL(idx)].change = tt[RR(idx)].change = 0; tt[idx].cover = mix; } break; case 'C': if(l == tt[idx].left && r == tt[idx].right) { tt[idx].Change(); return ; } if(tt[idx].cover != mix) { tt[LL(idx)].cover = tt[RR(idx)].cover = tt[idx].cover; tt[LL(idx)].change = tt[RR(idx)].change = 0; tt[idx].cover = mix; } mid = tt[idx].mid(); if(r <= mid) tt[RR(idx)].cover = tt[idx].change; if(mid < l) tt[LL(idx)].cover = tt[idx].change; break; case 'S': if(l == tt[idx].left && r == tt[idx].right) { tt[idx].Change(); return ; } if(tt[idx].cover != mix) { tt[LL(idx)].cover = tt[RR(idx)].cover = tt[idx].cover; tt[LL(idx)].change = tt[RR(idx)].change = 0; tt[idx].cover = mix; } break; } if(tt[idx].change) { tt[LL(idx)].Change(); tt[RR(idx)].Change(); tt[idx].change = 0; } mid = tt[idx].mid(); if(r <= mid) { update(l,r,op,LL(idx)); } else if(mid < l) { update(l,r,op,RR(idx)); } else { update(l,mid,op,LL(idx)); update(mid+1,r,op,RR(idx)); } if(tt[LL(idx)].cover == tt[RR(idx)].cover) { tt[idx].cover = tt[LL(idx)].cover; } } void query(int l,int r,int idx) { if(l == r) { if(tt[idx].cover) { hash[l] = true; } return ; } if(tt[idx].cover != mix) { tt[LL(idx)].cover = tt[RR(idx)].cover = tt[idx].cover; tt[LL(idx)].change = tt[RR(idx)].change = 0; tt[idx].cover = mix; } if(tt[idx].change) { tt[LL(idx)].Change(); tt[RR(idx)].Change(); tt[idx].change = 0; } int mid = tt[idx].mid(); query(l,mid,LL(idx)); query(mid+1,r,RR(idx)); } int M = 131072; int main() { build(0,M,1); char op[2]; char str[99]; while(scanf("%s%s",op,str) == 2) { int a(0),b(0); Scanf(a,b,str); if(a > b) { if(op[0] == 'C' || op[0] == 'I') { tt[1].cover = 0; tt[1].change = 0; } continue; } update(a,b,op[0],1); } CC(hash,false); query(0,M,1); bool flag = false; int start = -1,end; FF(i,M) { if(hash[i]) { if(start == -1) { start = i; } end = i; } else { if(start != -1) { if(flag) printf(" "); flag = true; Printf(start,end); start = -1; } } } if(!flag) { printf("empty set"); } puts(""); return 0; } |
.
19.pku2482 Stars in Your Window
成段更新,区间最值 + 扫描线(转化成区间最值有点巧妙,数据太TMD的恶心了,中间二分的地方会int溢出,检查了半个小时)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | struct Seg_Tree{ int left,right; int val; int add; int mid() { return (left + right)>>1; } }tt[40000]; struct star{ int x,y,val; }hh[10001]; int pos[10001]; int n , m , H, W; bool cmp(star &a,star &b) { return a.y < b.y; } int Bin(LL x) { int lo = 0; int hi = m - 1; while(lo <= hi) { int mid = (lo + hi) >> 1; if(pos[mid] < x) { lo = mid + 1; } else { hi = mid - 1; } } return lo; } void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].add = 0; tt[idx].val = 0; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int l,int r,int add,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { tt[idx].add += add; tt[idx].val += add; return ; } if(tt[idx].add) { tt[LL(idx)].add += tt[idx].add; tt[RR(idx)].add += tt[idx].add; tt[LL(idx)].val += tt[idx].add; tt[RR(idx)].val += tt[idx].add; tt[idx].add = 0; } int mid = tt[idx].mid(); if(l <= mid) update(l,r,add,LL(idx)); if(mid < r) update(l,r,add,RR(idx)); tt[idx].val = max(tt[LL(idx)].val , tt[RR(idx)].val); } int main() { while(scanf("%d%d%d",&n,&W,&H) == 3) { FF(i,n) { scanf("%d%d%d",&hh[i].x,&hh[i].y,&hh[i].val); pos[i] = hh[i].x; } sort(hh,hh+n,cmp); sort(pos,pos+n); m = 0; FF(i,n) { if(i == 0 || pos[i] != pos[i-1]) { pos[m++] = pos[i]; } } build(0,m-1,1); int start = 0,end = 0; int ans = 0; FF(i,n) { if(i && hh[i].y == hh[i-1].y) continue; FOR(j,start,i) { update(Bin(hh[j].x) , Bin(hh[j].x + W) - 1, -hh[j].val , 1); } start = i; int lo = i; int hi = n-1; LL buf = (LL)hh[i].y + H; while(lo <= hi) { int mid = (lo + hi) >> 1; if(hh[mid].y < buf) { lo = mid + 1; } else { hi = mid - 1; } } FOR(j,end,lo) { update(Bin(hh[j].x) , Bin((LL)hh[j].x + W) - 1, hh[j].val , 1); } end = lo; checkmax(ans,tt[1].val); if(end == n) break; } printf("%d\n",ans); } return 0; } |
.
20.pku2828 Buy Tickets
思维很巧妙,倒过来做的话就能确定此人所在的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | struct Seg_Tree{ int left,right; int remain; int mid() { return (left + right) >> 1; } }tt[600000]; int pos[200001]; int newpos[200001]; int val[200001]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].remain = r - l + 1; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } int query(int id,int idx) { tt[idx].remain --; if(tt[idx].left == tt[idx].right) { return tt[idx].left; } if(tt[LL(idx)].remain >= id) { return query(id,LL(idx)); } else { return query(id-tt[LL(idx)].remain,RR(idx)); } } int main() { int n; while(scanf("%d",&n) == 1) { build(0,n-1,1); FF(i,n) { scanf("%d%d",&pos[i],&val[i]); } FFD(i,n) { newpos[query(pos[i]+1,1)] = i; } FF(i,n-1) { printf("%d ",val[newpos[i]]); } printf("%d\n",val[newpos[n-1]]); } return 0; } |
.
21.pku2464 Brownie Points II
更新节点,区间求和 + 扫描线(很好玩的一道题目,用两个线段树沿着扫描线更新,然后按”自己最多,对方最少”的方案一路统计)
(因为两棵树,我就直接写成类了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | class Key { private: struct Seg_Tree{ int left; int right; int sum; int mid() { return (left + right) >> 1; } }tt[600000]; public: void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].sum = 0; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int pos,int st,int idx) { if(tt[idx].left == tt[idx].right) { tt[idx].sum += st; return ; } int mid = tt[idx].mid(); if(pos <= mid) { update(pos,st,LL(idx)); } else { update(pos,st,RR(idx)); } tt[idx].sum = tt[LL(idx)].sum + tt[RR(idx)].sum; } int query(int l,int r,int idx) { if(l == tt[idx].left && r == tt[idx].right) { return tt[idx].sum; } int mid = tt[idx].mid(); if(r <= mid) { return query(l,r,LL(idx)); } else if(mid < l) { return query(l,r,RR(idx)); } else { return query(l,mid,LL(idx)) + query(mid+1,r,RR(idx)); } } }Left,Right; struct Point { int x,y; }p[200001]; int pos[200010]; bool cmp(Point &a,Point &b) { return a.x < b.x; } int m; int Bin(int x) { int lo = 1; int hi = m - 1; while(lo <= hi) { int mid = (lo + hi) >> 1; if(pos[mid] == x) { return mid; } if(pos[mid] < x) { lo = mid + 1; } else { hi = mid - 1; } } return -1; } vector <int> ans; int main() { int n; while(scanf("%d",&n) == 1) { if(n == 0) break; FF(i,n) { scanf("%d%d",&p[i].x,&p[i].y); pos[i+1] = p[i].y; } sort(pos+1,pos+n+1); sort(p,p+n,cmp); m = 1; FOR(i,1,n+1) { if(i == 1 || pos[i] != pos[i-1]) { pos[m++] = pos[i]; } } Left.build(0,m,1); Right.build(0,m,1); FF(i,n) { Right.update(Bin(p[i].y),1,1); } int start = 0; int best = 0; ans.clear(); FOR(i,1,n+1) { if(i == n || p[i].x != p[i-1].x) { FOR(j,start,i) { Right.update(Bin(p[j].y),-1,1); } int Ollie = -1; int Stan = -1; FOR(j,start,i) { int idx = Bin(p[j].y); int A = Left.query(0,idx-1,1) + Right.query(idx+1,m,1); int B = Left.query(idx+1,m,1) + Right.query(0,idx-1,1); if(Ollie == B) { Stan = min(Stan , A); } else if(Ollie < B) { Ollie = B; Stan = A; } } if(Stan > best) { best = Stan; ans.clear(); } if(Stan == best) { ans.push_back(Ollie); } FOR(j,start,i) { Left.update(Bin(p[j].y),1,1); } start = i; } } printf("Stan: %d; Ollie:",best); sort(ans.begin(),ans.end()); FF(i,sz(ans)) { if(i == 0 || ans[i] != ans[i-1]) { printf(" %d",ans[i]); } } puts(";"); } return 0; } |
.
22.pku3145 Harmony Forever
查找一个区间内最左边的数,询问的val大的话用线段树,小的话线性扫描,很囧的题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | struct Seg_Tree{ int left,right; bool exist; bool unexist; int mid() { return (left + right) >> 1; } }tt[2000000]; int num[40010]; int rank[5000001]; #define M 50000 void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].exist = false; tt[idx].unexist = false; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int id,int idx) { tt[idx].exist = true; if(tt[idx].left == tt[idx].right) { return ; } if(tt[idx].unexist) { tt[LL(idx)].unexist = tt[RR(idx)].unexist = true; tt[LL(idx)].exist = tt[RR(idx)].exist = false; tt[idx].unexist = false; } int mid = tt[idx].mid(); if(id <= mid) { update(id,LL(idx)); } else { update(id,RR(idx)); } } int query(int l,int r,int idx) { if(tt[idx].left == tt[idx].right) { return tt[idx].left; } if(tt[idx].unexist) { tt[LL(idx)].unexist = tt[RR(idx)].unexist = true; tt[LL(idx)].exist = tt[RR(idx)].exist = false; tt[idx].unexist = false; } int mid = tt[idx].mid(); int buf = -1; if(l <= mid) { if(tt[LL(idx)].exist) { buf = query(l,r,LL(idx)); } } if(buf != -1) return buf; if(mid < r) { if(tt[RR(idx)].exist) { buf = query(l,r,RR(idx)); } } return buf; } int main() { build(0,500000,1); int T, cas = 1; while(scanf("%d",&T) == 1) { if(T == 0) break; if(cas != 1) { puts(""); } printf("Case %d:\n",cas++); tt[1].unexist = true; int n = 0; while(T --) { char op[2]; int val; scanf("%s%d",op,&val); if(op[0] == 'B') { update(val,1); num[n++] = val; rank[val] = n; } else { if(n == 0) { puts("-1"); continue; } if(val <= 1000) { int remain = val; int last = -1; FFD(i,n) { int buf = num[i] % val; if(buf < remain) { remain = buf; last = i+1; } if(remain == 0) { break; } } printf("%d\n",last); } else { int remain = val; int last = -1; int start = 0; int end = val - 1; while(start <= 500000) { checkmin(end,500000); int key = query(start,end,1); if(key != -1) { int buf = key % val; if(buf < remain) { remain = buf; last = rank[key]; } else if(buf == remain) { checkmax(last,rank[key]); } } start += val; end += val; } printf("%d\n",last); } } } } return 0; } |
.
23.pku2886 Who Gets the Most Candies?
寻找区间中的左数第N个数,约瑟夫环(学到了反素数表,可以不用把所有数字预处理出来了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | struct Seg_Tree{ int left,right; int sum; int mid() { return (left + right) >> 1; } }tt[1100000]; struct H{ char name[12]; int val; }hh[500001]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].sum = (r - l + 1); if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } int update(int k,int idx) { tt[idx].sum --; if(tt[idx].left == tt[idx].right) { return tt[idx].left; } int mid = tt[idx].mid(); if(k <= tt[LL(idx)].sum) return update(k,LL(idx)); return update(k-tt[LL(idx)].sum,RR(idx)); } const int antiprime[] = {1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320, 221760, 277200, 332640, 498960, 554400, 665280}; const int factorNum[] = {1, 2, 3, 4, 6, 8, 9, 10, 12, 16, 18, 20, 24, 30, 32, 36, 40, 48, 60, 64, 72, 80, 84, 90, 96, 100, 108, 120, 128, 144, 160, 168, 180, 192, 200, 216, 224}; int main() { int n , k, &mod = tt[1].sum; while(scanf("%d%d",&n,&k) == 2) { FOR(i,1,n+1) { scanf("%s%d",hh[i].name,&hh[i].val); } build(1,n,1); int tag=0; while(antiprime[tag] <= n) { tag++; } int need = antiprime[--tag]; int pos = 0; hh[pos].val = 0; while(need --) { if(hh[pos].val > 0) { k = ((k + hh[pos].val - 2)%mod + mod)%mod + 1; } else { k = ((k + hh[pos].val - 1)%mod + mod)%mod + 1; } pos = update(k,1); } printf("%s %d\n",hh[pos].name,factorNum[tag]); } return 0; } |
.
24.pku2991 Crane
记录了线段的两端点以及转过的角度,成段的转,超有意思的题目,做了之后会对线段树理解更深刻
(wy教主推荐的,不过我的代码写的太搓了..没啥学习的价值)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | #define M 10001 struct Point { double x,y; Point operator + (Point a) { Point ret; ret.x = x + a.x; ret.y = y + a.y; return ret; } Point operator - (Point a) { Point ret; ret.x = x - a.x; ret.y = y - a.y; return ret; } }; struct Seg_Tree{ int left,right; int angle; Point s,e; bool cover; int mid() { return (left + right) >> 1; } void turn(int angle) { Point ret = s; Point buf = s; e.x -= s.x; e.y -= s.y; buf.x = cos(angle*Pi/180); buf.y = sin(angle*Pi/180); ret.x += e.x*buf.x - e.y*buf.y; ret.y += e.x*buf.y + e.y*buf.x; e = ret; } }tt[M*4]; int len[M]; int sum[M]; void build(int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].s.x = 0; tt[idx].s.y = sum[l]-len[l]; tt[idx].e.x = 0; tt[idx].e.y = sum[r]; tt[idx].angle = 0; tt[idx].cover = false; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update(int idx) { int l = LL(idx); int r = RR(idx); tt[l].angle = (tt[l].angle + tt[idx].angle)%360; tt[l].e = tt[l].e + tt[idx].s - tt[l].s; tt[l].s = tt[idx].s; tt[l].turn(tt[idx].angle); tt[l].cover = true; tt[r].e = tt[r].e + tt[l].e - tt[r].s; tt[r].s = tt[l].e; tt[r].angle = (tt[r].angle + tt[idx].angle)%360; tt[r].turn(tt[idx].angle); tt[r].cover = true; tt[idx].angle = 0; tt[idx].cover = false; } void update(int l,int a,int idx) { if(tt[idx].left == l) { tt[idx].angle = (tt[idx].angle + a)%360; tt[idx].turn(a); tt[idx].cover = true; return ; } if(tt[idx].cover) { update(idx); } int mid = tt[idx].mid(); if(l <= mid) { update(l,a,LL(idx)); tt[RR(idx)].e = tt[RR(idx)].e + tt[LL(idx)].e - tt[RR(idx)].s; tt[RR(idx)].s = tt[LL(idx)].e; update(mid+1,a,RR(idx)); } else { update(l,a,RR(idx)); } tt[idx].e = tt[RR(idx)].e; } int query(int id,int idx) { if(tt[idx].left == tt[idx].right) { return tt[idx].angle; } if(tt[idx].cover) { update(idx); } int mid = tt[idx].mid(); if(id <= mid) { return query(id,LL(idx)); } else { return query(id,RR(idx)); } tt[idx].e = tt[RR(idx)].e; } int main() { int n , m; int cas = 0; while(scanf("%d%d",&n,&m) == 2) { if(cas) puts(""); cas ++; FOR(i,1,n+1) { scanf("%d",&len[i]); sum[i] = sum[i-1] + len[i]; } build(1,n,1); while(m --) { int id,a; scanf("%d%d",&id,&a); a = ((180 - query(id+1,1) + query(id,1) + a) % 360 + 360)%360; update(id+1,a,1); printf("%.2lf %.2lf\n",tt[1].e.x+eps,tt[1].e.y+eps); } } return 0; } |
.
25.hdu1823 Luck and Love
二维线段树,没啥意思,代码量大了一倍而已,题目和运用范围都没一维的广,随便找了道题目练习下就好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | struct Sub_Seg_Tree { int left; int right; int val; int mid() { return (left + right) >> 1; } }; struct Seg_Tree{ int left; int right; Sub_Seg_Tree tt[1001*4]; int mid() { return (left + right) >> 1; } }tt[101*4]; void build2(Sub_Seg_Tree tt[],int l,int r,int idx) { tt[idx].left = l; tt[idx].right = r; tt[idx].val = -1; if(l == r) return ; int mid = tt[idx].mid(); build2(tt,l,mid,LL(idx)); build2(tt,mid+1,r,RR(idx)); } void build(int l,int r,int idx) { build2(tt[idx].tt,0,1000,1); tt[idx].left = l; tt[idx].right = r; if(l == r) return ; int mid = tt[idx].mid(); build(l,mid,LL(idx)); build(mid+1,r,RR(idx)); } void update2(Sub_Seg_Tree tt[],int b,int val,int idx) { if(tt[idx].left == tt[idx].right) { checkmax(tt[idx].val,val); return ; } if(b <= tt[idx].mid()) { update2(tt,b,val,LL(idx)); } else { update2(tt,b,val,RR(idx)); } tt[idx].val = max(tt[LL(idx)].val,tt[RR(idx)].val); } void update(int a,int b,int val,int idx) { update2(tt[idx].tt,b,val,1); if(tt[idx].left == tt[idx].right) return ; if(a <= tt[idx].mid()) { update(a,b,val,LL(idx)); } else { update(a,b,val,RR(idx)); } } int query2(Sub_Seg_Tree tt[],int l,int r,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { return tt[idx].val; } int mid = tt[idx].mid(); int ret = -1; if(l <= mid) checkmax(ret,query2(tt,l,r,LL(idx))); if(mid < r) checkmax(ret,query2(tt,l,r,RR(idx))); return ret; } int query(int l,int r,int l2,int r2,int idx) { if(l <= tt[idx].left && r >= tt[idx].right) { return query2(tt[idx].tt,l2,r2,1); } int mid = tt[idx].mid(); int ret = -1; if(l <= mid) checkmax(ret,query(l,r,l2,r2,LL(idx))); if(mid < r) checkmax(ret,query(l,r,l2,r2,RR(idx))); return ret; } int main() { int T; while(scanf("%d",&T) == 1) { if(T == 0) break; build(100,200,1); while(T --) { char op; while(!isalpha(op = getchar())); if(op == 'I') { int a; double b,c; scanf("%d%lf%lf",&a,&b,&c); update(a,int(b*10),int(c*10),1); } else { int l1,r1; double l2,r2; scanf("%d%d%lf%lf",&l1,&r1,&l2,&r2); if(l1 > r1) swap(l1,r1); if(l2 > r2) swap(l2,r2); int ret = query(l1,r1,int(l2*10),int(r2*10),1); if(ret < 0) { puts("-1"); } else { printf("%.1lf\n",ret/10.0); } } } } return 0; } |
Popularity: 100% [?]
man down 其实可以不那么做。。。
[回复]
虽然还没有全部AC掉,但是感觉应该留一个脚印,嘿嘿,万分膜拜
[回复]
[...] 【线段树专辑】:http://www.notonlysuccess.com/?p=59 [...]
Hotel那题里
int query(int w,int idx) {
if(tt[idx].left == tt[idx].right && w == 1) {//师兄,这个w==1什么意思
return tt[idx].left;
}
好像去掉 && w==1这个判断条件,也能A, 而且时间更短……
但是不知道,加这个什么意思?
酷~行天下´s last blog ..HDU 2838 Cow Sorting(树状数组)
[回复]
看了大牛第17个的*2 和vector ,感觉自己用set写的代码好搓,
[回复]
现在才知道,模板的每一句话都是经过深思熟虑得出来的。比如节点里的 mid 函数,idx 写在后面等。现在才体会到。
[回复]
[...] 这是我做的第一道线段树,因为花费了大半天的时间才基本上弄明白了,而且能再很快独自写出POJ2886,但是最悲剧的是2886题我把线段树的数组开小了一半,深度应该是16让我算成了15(这是后话)。在把HH线段树专辑里面的这题的代码默写了整整五遍后终于自己把这题写出来了(背着),其实一开始我明白这个思想,但是没用位运算来压缩颜色,而是用颜色的值看是不是线段树上的这段区间是单色的,但是死活就是通不过,具体哪里有错误实在是检查不出来,但是HH的代码很容易理解,而且基本所有题都是这个模板。需要注意的地方就是: 1:在update就是覆盖颜色的时候用的条件是l=tt[idx].r属于完全包含这段线段的条件。 2:最重要的一点,也是我一开始自己摸索着写的时候犯的错误:当要染色的这段线段不能包含线段树上的结点的时候,也就说明待染色的线段只能染当前结点线段的一部分,所以如果这个结点的cover是true,就要把结点的cover设置成false,并且把它的颜色赋值给两个孩子,并把孩子的cover设置成true。因为在染这个父亲的时候,是不用去管孩子的。比如[1,3]这个线段,一开始染了[1,2],染成了100颜色值。这时候[1,3]的cover肯定是false,而[1,2]的cover是true。然后下个操作染[1,3],染成200,代码里if(l=tt[idx].right){ tt[idx].col = (1 [...]
[...] —— 线段树专辑 notonlysuccess poj 1436 Horizontally Visible Segments_云卷云舒_百度空间 [...]
请问宏定义的 LL(n) RR(n) 分别是2n和2n + 1吧?
[回复]
第三题的query函数写得太繁了吧
直接
int query(int i)
{
if(tt[i].col!=-1)
return (tt[i].r-tt[i].l+1)*tt[i].col;
return query(2*i)+query(2*i+1);
}就解决了
[回复]
请问大牛,建立的线段树,左端-右端=0是叶子节点,那为什么你开的线段树数组下标最大都是3*n?我觉得最大4*n应该是没问题的。
[回复]
shǎ崽 回复:
一月 21st, 2011 at 20:19
是应该4倍的,以前写的代码没改过来~:)
[回复]
菜鸟 回复:
一月 22nd, 2011 at 12:20
哦····但是貌似开3倍的都能过啊···呵呵···是不是因为n很大的时候下标才有可能超过3*n,但是n很大的时候就算开3*n也会MLE,所以开3*n也能过···个人想法而已···
[回复]
shǎ崽 回复:
一月 22nd, 2011 at 12:24
这个空间其实是这么算的.
最少需要开比maxn大的最小的2^n次的两倍
如果maxn是2n-1的话,只需要开2^n+1的空间就够了
如果是2n+1的话,则需要开2^n+2
所以一般情况下3倍就能过
而最最极端的情况下需要4倍
[回复]
菜鸟 回复:
一月 23rd, 2011 at 17:14
谢谢大牛。请问大牛一般都是花一段时间来专门搞一个方向的题目?
[回复]
请问一下,那个17题坐标乘2是为啥??
[回复]
查询的时候为什么要传递子区间
[回复]
扫描线没法看懂 啊
[回复]
都是好题!
[回复]
今天刚学线段树,正愁没验证题做。
这下,做不过来了,还可以自己挑。
[回复]
poj 3325 代码里面CC 代表什么
[回复]
神牛的代码果然不是一般人能看的,用了一次C++引用,我就没读懂代码了.
[回复]
发现 数据结构 题的算法都好神奇….学习-ing
[回复]
发现自己太弱了,一道不看大牛代码就敲不出来 = =||,万分膜拜大牛Orz~~
另求Man Down的n多define…
[回复]
Ambition 回复:
九月 10th, 2010 at 17:46
额,终于搞懂了那个神一般的checkmax,dp太弱了,罪过啊…
[回复]
shǎ崽 回复:
九月 11th, 2010 at 12:05
是我没说明,罪过。。。
[回复]
您好 谢谢你的线段树专题 麻烦问一下 你的那个
12.hdu2871 Memory Control这道题目的二分是怎么想的 我的老是写挂呢 谢谢了 期待您的回复
[回复]
notonlysuccess 回复:
九月 8th, 2010 at 21:41
我很偷懒的,写了个vector来出来,直接暴力的用insert和erase
不然要手写平衡二叉树,代码量太大了~详细可以看我上边的代码
[回复]
我也在郁闷第十道题(poj 3667)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[回复]