poj 线段树

   题目:http://poj.org/problem?id=2777

应该说是线段树里面的最裸的那种了吧。题意:给你一段线段,分成单位长度,开始时每段的颜色都为 1 ,然后两种操作,一种:C A B K,是从A 开始到 B 这段距离用 K 来染色。另一种 P A B,询问 从A 到 B一共有多少种颜色。

View Code
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <queue>
  5 #include <stack>
  6 #include <algorithm>
  7 #include <math.h>
  8 #define N 100010
  9 #define M 10
 10 #define _clr(a,val) (memset(a,val,sizeof(a)))
 11 
 12 using namespace std;
 13 
 14 int n,num,sum;
 15 int mark[40];
 16 int ans;
 17 struct node
 18 {
 19     int l;
 20     int r;
 21     int c;
 22 }le[N * 3];
 23 void build(int s,int e,int d)
 24 {
 25     le[d].l = s;
 26     le[d].r = e;
 27     if(s == e) return ;
 28     int mid = (s + e) / 2;
 29     build(s,mid,d * 2);
 30     build(mid + 1,e,d * 2 + 1);
 31 }
 32 void insert(int s,int e,int d,int co)
 33 {
 34     if(le[d].l == s && le[d].r == e)
 35     {
 36         le[d].c = co;
 37     }
 38     else
 39     {
 40         int mid = (le[d].r + le[d].l) / 2;
 41         if(le[d].c > 0){le[d * 2].c = le[d * 2 + 1].c = le[d].c; le[d].c = -1;}
 42         if(e <= mid) insert(s,e,d * 2,co);
 43         else if(s > mid) insert(s,e,d * 2 + 1,co);
 44         else
 45         {
 46             insert(s, mid, d * 2, co);
 47             insert(mid + 1, e, d * 2 + 1,co);
 48         }
 49     }
 50 }
 51 void countree(int s,int e,int d)
 52 {
 53     if(le[d].c > 0)
 54     {
 55         mark[le[d].c] = 1;
 56     }
 57     else
 58     {
 59         int mid = (le[d].l + le[d].r) / 2;
 60         if(e <= mid) countree(s,e,d * 2);
 61         else if(s > mid) countree(s,e,d * 2 + 1);
 62         else
 63         {
 64             countree(s,mid,d * 2);
 65             countree(mid + 1, e,d * 2 + 1);
 66         }
 67     }
 68 }
 69 int main()
 70 {
 71     int i,j;
 72     char ch;
 73     int x,y,z;
 74     //freopen("data.txt","r",stdin);
 75     while(scanf("%d%d%d",&n,&num,&sum) != EOF)
 76     {
 77         //getchar();
 78         build(1,n,1);
 79         le[1].c = 1;
 80         while(sum--)
 81         {
 82             getchar();
 83             scanf("%c",&ch);
 84             if(ch == 'C')
 85             {
 86                 scanf("%d%d%d",&x,&y,&z);
 87                 if(x > y)
 88                 {
 89                     int tem = x;
 90                     x = y;
 91                     y = tem;
 92                 }
 93                 insert(x,y,1,z);
 94             }
 95             else if(ch == 'P')
 96             {
 97                 scanf("%d%d",&x,&y);
 98                 if(x > y)
 99                 {
100                     int tem = x;
101                     x = y;
102                     y = tem;
103                 }
104                 _clr(mark,0);
105                 ans = 0;
106                 countree(x,y,1);
107                 for(i = 1; i <= num; i++)
108                 {
109                     if(mark[i])
110                     {
111                         ans++;
112                     }
113                 }
114 
115                 printf("%d\n",ans);
116             }
117         }
118     }
119     return 0;
120 }

题目:http://poj.org/problem?id=2528

题意:给出一段距离,然后给你n行数,每行是从 A 到 B 这段距离涂抹一种颜色,问到最后,这段距离可以看见多少种不同的颜色。

思路:其实题目倒也不难,就是题目给的数据需要离散化处理一下。把输入的点离散化后,建树,插入,询问

View Code
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #define N  20010
  6 #define _clr(a,val) (memset(a,val,sizeof(a)))
  7 
  8 using namespace std;
  9 
 10 struct tree
 11 {
 12     int l;
 13     int r;
 14     int c;
 15 }tr[N * 4];
 16 struct node
 17 {
 18     int num;
 19     int il;
 20     int ind;
 21 }map[N * 2];
 22 int temp[N * 2][2];
 23 int mark[N];
 24 int cnt;
 25 int cmp(node a,node b)
 26 {
 27     return a.num < b.num;
 28 }
 29 void build(int s,int e,int d)
 30 {
 31     tr[d].l = s;
 32     tr[d].r = e;
 33     tr[d].c = -1;
 34     if(s == e) return ;
 35     int mid = (s + e) / 2;
 36     build(s, mid, d * 2);
 37     build(mid + 1, e, d * 2 + 1);
 38 }
 39 void insert(int s,int e,int d,int co)
 40 {
 41     if(tr[d].l == s && tr[d].r == e)
 42     {
 43         tr[d].c = co;return;
 44     }
 45     if(tr[d].c > 0) {tr[d * 2].c = tr[d * 2 + 1].c = tr[d].c;tr[d].c = -1;}
 46     int mid = (tr[d].l + tr[d].r) / 2;
 47     if(e <= mid) insert(s,e,d * 2,co);
 48     else if(s > mid) insert(s,e,d * 2 + 1,co);
 49     else
 50     {
 51         insert(s,mid,d * 2,co);
 52         insert(mid + 1,e,d * 2 + 1,co);
 53     }
 54 }
 55 void countree(int d)
 56 {
 57     if(tr[d].c != -1)
 58     {
 59         if( !mark[tr[d].c] )
 60         {
 61             mark[tr[d].c] = 1;
 62             cnt++;
 63         }
 64         return ;
 65     }
 66     countree(d * 2);
 67     countree(d * 2 + 1);
 68 }
 69 int main()
 70 {
 71     int i;
 72     int t,n;
 73     //freopen("data.txt","r",stdin);
 74     scanf("%d",&t);
 75     while(t--)
 76     {
 77         _clr(map,0);
 78         scanf("%d",&n);
 79         int tnum = 0;
 80         for(i = 0; i < n; i++)
 81         {
 82             scanf("%d%d",&temp[i][0],&temp[i][1]);
 83             map[tnum].num = temp[i][0];
 84             map[tnum].il = 1;
 85             map[tnum].ind = i;
 86             tnum++;
 87 
 88             map[tnum].num = temp[i][1];
 89             map[tnum].il = 0;
 90             map[tnum].ind = i;
 91             tnum ++;
 92         }
 93         sort(map,map + tnum,cmp);
 94         int tem = -1;
 95         int indx = 0;
 96         for(i = 0; i < tnum; i++)  // 离散化点
 97         {
 98             if(map[i].num != tem)
 99             {
100                 indx ++;
101                 tem = map[i].num;
102             }
103             if(map[i].il)
104             temp[map[i].ind][0] = indx;
105             else
106             temp[map[i].ind][1] = indx;
107         }
108         build(1,indx,1);
109         for(i = 0; i < n; i++)
110         {
111             insert(temp[i][0],temp[i][1],1,i + 1);
112         }
113         _clr(mark,0);
114         cnt = 0;
115         countree(1);
116         cout<<cnt<<endl;
117     }
118     return 0;
119 }

题目:http://poj.org/problem?id=2828

题意:一队人买票,给出第 i 个人站在 a 的后面,拥有的价值量为 b ,给出n行数据,问最后这些人的价值量顺序

思路:要说用线段树那段倒不难,关键是想出这个要倒着往线段树里插数据,因为不管这些人怎么站,最后一个人的位置是固定,然后推出倒数第二个人,依次往前推,所以要倒这插入数据

View Code
 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 #define N 200010
 6 #define _clr(a,val) (memset(a,val,sizeof(a)))
 7 
 8 using namespace std;
 9 
10 struct node
11 {
12     int l;
13     int r;
14     int num;
15 }tr[N * 4];
16 int mark[N];
17 int val[N],pla[N];
18 void build(int s,int e,int d)
19 {
20     tr[d].l = s;
21     tr[d].r = e;
22     tr[d].num = (e - s + 1);  // 此区间站的人数
23     if(s == e) return;
24     int mid = (s + e) / 2;
25     build(s, mid, d * 2);
26     build(mid + 1, e, d * 2 + 1);
27 }
28 void insert(int d,int i)
29 {
30     tr[d].num--;  
31     if(tr[d].l == tr[d].r)
32     mark[tr[d].l] = val[i];
33     else
34     {
35         if(tr[d * 2].num > pla[i])  // 左边站的人数足够,去左孩子查找
36         insert(d * 2,i);
37         else   // 否则去右孩子查找
38         {
39             pla[i] -= tr[d * 2].num;  // 去掉左孩子上的人数
40             insert(d * 2 + 1,i);
41         }
42     }
43 }
44 int main()
45 {
46     int i,n;
47     //freopen("data.txt","r",stdin);
48     while(scanf("%d",&n) != EOF)
49     {
50         _clr(val,0);
51         _clr(pla,0);
52         _clr(mark,0);
53         for(i = 1; i <= n; i++)
54         scanf("%d%d",&pla[i],&val[i]);
55         build(1,n,1);
56         for(i = n; i >= 1; i--)
57         {
58             insert(1,i);
59         }
60         for(i = 1;i < n; i++)
61         printf("%d ",mark[i]);
62         printf("%d\n",mark[n]);
63     }
64     return 0;
65 }

 

原文地址:https://www.cnblogs.com/fxh19911107/p/2613127.html