LightOj1089(求点包含几个线段 + 线段树)
Posted zhaop
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOj1089(求点包含几个线段 + 线段树)相关的知识,希望对你有一定的参考价值。
题意:n( n <= 50000 ) 个线段,q ( q <= 50000) 个点,问每个点在几个线段上
线段端点的和询问的点的值都很大,所以必须离散化
第一种解法:先把所有的线段端点和询问点,离散处理,然后对于每条选段处理,c[x]++, c[y + 1]--,然后令c[x] = c[x] + c[x - 1],所以c[x]就保存了被几个线段覆盖,然后对对于每个询问点,查找他在离散后的位置,然后直接读取c[],这种方法很巧妙,佩服佩服
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 const int Max = 50000 + 10; 7 int c[4 * Max],a[Max],b[Max],querry[Max]; 8 int id[4 * Max],cnt; 9 int main() 10 { 11 int n, p, test; 12 scanf("%d", &test); 13 for(int t = 1; t <= test; t++) 14 { 15 printf("Case %d:\n", t); 16 scanf("%d%d", &n, &p); 17 memset(c, 0, sizeof(c)); 18 cnt = 0; 19 for(int i = 1; i <= n; i++) 20 { 21 scanf("%d%d", &a[i], &b[i]); 22 id[cnt++] = a[i]; 23 id[cnt++] = b[i]; 24 } 25 for(int i = 1; i <= p; i++) 26 { 27 scanf("%d", &querry[i]); 28 id[cnt++] = querry[i]; 29 } 30 sort(id, id + cnt); 31 cnt = unique(id, id + cnt) - id; 32 for(int i = 1; i <= n; i++) 33 { 34 int x = lower_bound(id, id + cnt, a[i]) - id; 35 int y = lower_bound(id, id + cnt, b[i]) - id; 36 c[x]++; 37 c[y + 1]--; 38 } 39 for(int i = 1; i < 3 * Max; i++) 40 c[i] += c[i - 1]; 41 42 for(int i = 1; i <= p; i++) 43 { 44 int x = lower_bound(id, id + cnt, querry[i]) - id; 45 printf("%d\n", c[x]); 46 } 47 } 48 return 0; 49 }
线段树也可解,只是RE
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 const int Max = 50000 + 10; 7 struct node 8 { 9 int l,r; 10 int tag,cnt; 11 }; 12 node tree[4 * Max]; 13 int a[4 * Max], b[4 * Max], c[4 * Max], querry[Max]; 14 int tot; 15 void buildTree(int left, int right, int k) 16 { 17 tree[k].l = left; 18 tree[k].r = right; 19 tree[k].tag = -1; 20 tree[k].cnt = 0; 21 if(left == right) 22 return; 23 int mid = (left + right) / 2; 24 buildTree(left, mid, k * 2); 25 buildTree(mid + 1, right, k * 2 + 1); 26 } 27 void upDate(int left, int right, int k, int newp) 28 { 29 if(tree[k].tag != -1) 30 { 31 tree[k * 2].tag = tree[k * 2 + 1].tag = tree[k].tag; 32 tree[k * 2].cnt++; 33 tree[k * 2 + 1].cnt++; 34 tree[k].tag = -1; 35 } 36 if(tree[k].l == left && tree[k].r == right) 37 { 38 tree[k].cnt++; 39 tree[k].tag = newp; 40 return; 41 } 42 int mid = (tree[k].l + tree[k].r) / 2; 43 if(right <= mid) 44 upDate(left, right, k * 2, newp); 45 else if(mid < left) 46 upDate(left, right, k * 2 + 1, newp); 47 else 48 { 49 upDate(left, mid, k * 2, newp); 50 upDate(mid + 1, right, k * 2 + 1, newp); 51 } 52 } 53 int Search(int k, int value) 54 { 55 if(tree[k].l == tree[k].r) 56 return tree[k].cnt; 57 if(tree[k].tag != -1) 58 { 59 tree[k * 2].tag = tree[k * 2 + 1].tag = tree[k].tag; 60 tree[k * 2].cnt++; 61 tree[k * 2 + 1].cnt++; 62 tree[k].tag = -1; 63 } 64 65 int mid = (tree[k].l + tree[k].r) / 2; 66 if(value <= mid) 67 return Search(k * 2, value); 68 else 69 return Search(k * 2 + 1, value); 70 } 71 int main() 72 { 73 int test, n, q; 74 scanf("%d", &test); 75 for(int t = 1; t <= test; t++) 76 { 77 scanf("%d%d", &n, &q); 78 tot = 0; 79 for(int i = 1; i <= n; i++) 80 { 81 scanf("%d%d", &a[i], &b[i]); 82 c[tot++] = a[i]; 83 c[tot++] = b[i]; 84 } 85 for(int i = 1; i <= q; i++) 86 { 87 scanf("%d", &querry[i]); 88 c[tot++] = querry[i]; 89 } 90 sort(c, c + tot); 91 tot = unique(c, c + tot) - c; 92 buildTree(1, tot, 1); 93 for(int i = 1; i <= n; i++) 94 { 95 int x = lower_bound(c, c + tot, a[i]) - c + 1; 96 int y = lower_bound(c, c + tot, b[i]) - c + 1; 97 upDate(x, y, 1, 1); 98 } 99 printf("Case %d:\n", t); 100 for(int i = 1; i <= q; i++) 101 { 102 int x = lower_bound(c, c + tot, querry[i]) - c + 1; 103 printf("%d\n", Search(1, x)); 104 } 105 } 106 return 0; 107 }
以上是关于LightOj1089(求点包含几个线段 + 线段树)的主要内容,如果未能解决你的问题,请参考以下文章
LightOJ 1097 - Lucky Number 线段树
LightOJ 1080 Binary Simulation (线段树&成段更新)
Codeforces 1089K - King Kog's Reception - [线段树][2018-2019 ICPC, NEERC, Northern Eurasia Finals P