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 }
View Code

线段树也可解,只是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 }
未AC

 

以上是关于LightOj1089(求点包含几个线段 + 线段树)的主要内容,如果未能解决你的问题,请参考以下文章

LightOJ 1093 - Ghajini 线段树

HDU 1556 线段树或树状数组,插段求点

LightOJ 1085(树状数组+离散化+DP,线段树)

LightOJ 1097 - Lucky Number 线段树

LightOJ 1080 Binary Simulation (线段树&成段更新)

Codeforces 1089K - King Kog's Reception - [线段树][2018-2019 ICPC, NEERC, Northern Eurasia Finals P