poj 2528 动态线段树

动态建立结点就不用离散化了,细节见代码,相信还是比较好理解的。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <set>
  5 using namespace std;
  6
  7 const int N = 500000;
  8 set<int> s;
  9 int cnt;
 10
 11 struct Node
 12 {
 13     int lc, rc, l, r, c;
 14     void init( int _l, int _r, int _c )
 15     {
 16         l = _l, r = _r, c = _c;
 17         lc = rc = -1;
 18     }
 19 } node[N << 2];
 20
 21 void pushdown( int i )
 22 {
 23     if ( node[i].c != -1 )
 24     {
 25         node[node[i].lc].c = node[i].c;
 26         node[node[i].rc].c = node[i].c;
 27         node[i].c = -1;
 28     }
 29 }
 30
 31 void update( int i, int l, int r, int c )
 32 {
 33     if ( node[i].l == l && node[i].r == r )
 34     {
 35         node[i].c = c;
 36         return ;
 37     }
 38     int mid = ( node[i].l + node[i].r ) >> 1;
 39     if ( node[i].lc == -1 )
 40     {
 41         node[i].lc = cnt;
 42         node[cnt].init( node[i].l, mid, -1 );
 43         cnt++;
 44     }
 45     if ( node[i].rc == -1 )
 46     {
 47         node[i].rc = cnt;
 48         node[cnt].init( mid + 1, node[i].r, -1 );
 49         cnt++;
 50     }
 51     pushdown(i);
 52     if ( r <= mid )
 53     {
 54         update( node[i].lc, l, r, c );
 55     }
 56     else if ( l > mid )
 57     {
 58         update( node[i].rc, l, r, c );
 59     }
 60     else
 61     {
 62         update( node[i].lc, l, mid, c );
 63         update( node[i].rc, mid + 1, r, c );
 64     }
 65 }
 66
 67 void dfs( int i )
 68 {
 69     if ( node[i].c != -1 )
 70     {
 71         s.insert( node[i].c );
 72         return ;
 73     }
 74     if ( node[i].lc != -1 ) dfs( node[i].lc );
 75     if ( node[i].rc != -1 ) dfs( node[i].rc );
 76 }
 77
 78 int main ()
 79 {
 80     int t;
 81     scanf("%d", &t);
 82     while ( t-- )
 83     {
 84         int n;
 85         scanf("%d", &n);
 86         node[0].init( 1, 10000000, -1 );
 87         cnt = 1;
 88         s.clear();
 89         for ( int i = 0; i < n; i++ )
 90         {
 91             int l, r;
 92             scanf("%d%d", &l, &r);
 93             if ( l > r ) swap( l, r );
 94             update( 0, l, r, i );
 95         }
 96         dfs(0);
 97         printf("%d\n", s.size());
 98     }
 99     return 0;
100 }
时间: 2024-07-31 21:32:28

poj 2528 动态线段树的相关文章

poj 2528 离散化+线段树

这个破题  我WA 了   我实在找不到我那里错了 题意:有一个墙,往墙上贴报纸,最后问能看到几张报纸 其实就是很容易的线段树,不容易的地方在于离散化 离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多这题的难点在于每个数字其实表示的是一个单位长度(并且一个点),这样普通的离散化会造成许多错误(包括我以前的代码,这题数据奇弱) 出下面两个简单的例子应该能体现普通离散化的缺陷: 1-10 1-4 5-10 1-10 1-4 6-10  为了解决这种缺陷,我们可以在排序

POJ 2528 QAQ线段树+离散化

Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u SubmitStatus Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all pl

poj 2528 Mayor&#39;s posters(动态线段树)

传送门:点击打开链接 题目大意: 给定一个 1 ~ 10000000 的区间,然后有N次操作(N <= 10000),第i次操作是将 l~r 区间覆盖为i.问最后一共有多少种有颜色. 解题思路: 一开始想到了离散化,但是想了一想感觉有点麻烦 然后就问专职搞数据结构的队友.然后他说了 动态线段树.思路如下: 定义一个ID.然后 根节点1表示掌管1-MAXN颜色的区间.然后每次都是动态的建树.当一个区间的左子区间还不存在时.建立它,并且记录下每个区间的左子区间和右子区间的ID.那么就可以搞了. 最后

POJ 2481 Cows (线段树)

Cows 题目:http://poj.org/problem?id=2481 题意:有N头牛,每只牛有一个值[S,E],如果对于牛i和牛j来说,它们的值满足下面的条件则证明牛i比牛j强壮:Si <=Sjand Ej <= Ei and Ei - Si > Ej - Sj.现在已知每一头牛的测验值,要求输出每头牛有几头牛比其强壮. 思路:将牛按照S从小到大排序,S相同按照E从大到小排序,这就保证了排在后面的牛一定不比前面的牛强壮.再按照E值(离散化后)建立一颗线段树(这里最值只有1e5,所

POJ 2299 离散化线段树

点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 40827   Accepted: 14752 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by

POJ训练计划2299_Ultra-QuickSort(线段树/单点更新)

解题报告 题意: 求逆序数. 思路: 线段树离散化处理. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define LL long long using namespace std; LL sum[2001000],num[501000],_hash[501000]; void push_up(int rt) { sum[rt]=sum[rt*2

POJ 3667(线段树区间合并)

http://poj.org/problem?id=3667 题意:两个操作 : 1 选出靠左的长度为a的区间. 2 把从 a到a+b的区间清空. 线段树区间合并+lazy // by caonima // hehe #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; co

POJ&#183;1151 Atlantis&#183;线段树求矩形面积并

题目在这:http://poj.org/problem?id=1151 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the is

POJ 2299 Ultra-QuickSort(线段树+离散化)

题目地址:POJ 2299 这题曾经用归并排序做过,线段树加上离散化也可以做.一般线段树的话会超时. 这题的数字最大到10^10次方,显然太大,但是可以利用下标,下标总共只有50w.可以从数字大的开始向树上加点,然后统计下标比它小即在它左边的数的个数.因为每加一个数的时候,比该数大的数已经加完了,这时候坐标在它左边的就是一对逆序数. 但是该题还有一个问题,就是数字重复的问题.这时候可以在排序的时候让下标大的在前面,这样就可以保证加点的时候下标比他小的数中不会出现重复的. 这题需要注意的是要用__