poj 2528 经典线段树入门

来源:互联网 发布:知君本无邪番外 编辑:程序博客网 时间:2024/06/05 21:05
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;/*对线段树离散化的理解, 把单位区间比较多,但是程序中有用不到那么多单位小区间,这时可以用线段树的离散化来处理,比如[1 3], [2 10], [4   6], [20 10000000]  可以离散化为     [1 3] [2 7] , [5  6],  [8 9]; 这样 我们就可以开一个a[10] 的数组来存储就行了, 节省大量的内存 开支,     离散化 ,白话一点 就是区间按不等 但合理的方式,缩小的产物,     以上为基本思想,其能演变的阵法,就靠自己的变通能力了。*/const int M = 10005;struct node{    int l, r;    int value;}Tree[16*M];int n, T;int vist[4*M];int num[4*M];//辅助离散化,int post[M][2];//存储海报前端和后端,int num2[4*M];//存储离散化后的数,int ans;int Find(int l, int r, int x){    int mid;    while(l <= r)    {        mid = (l + r)/2;        if(num2[mid] == x)            return mid;        else if(num2[mid] > x)        {            r = mid - 1;        }        else        {            l = mid + 1;        }    }    return 0;}void Make_Tree(int x, int y, int nu){    Tree[nu].l = x;    Tree[nu].r = y;    Tree[nu].value = 0;    if(x == y)        return;    else    {        int mid = (x + y)/2;        Make_Tree(x, mid, nu*2);        Make_Tree(mid + 1, y, nu*2 + 1);    }}void Add(int x, int y, int c, int nu){    if(Tree[nu].l >= x && Tree[nu].r <= y)//整个区间都被覆盖,    {        Tree[nu].value = c;        return ;    }    else    {        int mid;        if(Tree[nu].value > 0)//当前区间如果被覆盖过, 则整个区间都被覆盖着,向下传时,也将覆盖整个子区间,        {            Tree[nu*2].value = Tree[nu].value;            Tree[nu*2 + 1].value = Tree[nu].value;            Tree[nu].value = 0;        }        mid = (Tree[nu].l + Tree[nu].r)/2;//向下查找,当前区间能够覆盖的子区间,        if(x <= mid)            Add(x, y, c, nu*2);        if(y > mid)            Add(x, y, c, nu*2 +1);    }}void query(int x, int y, int nu){    if(Tree[nu].value > 0) { //表示 此区间当前被覆盖;        int in = Tree[nu].value;      if(!vist[in]) {        ans++;        vist[in] = 1;      }    return;    }    else {  //继续查找被覆盖的小区间,        if(x == y)            return;            int mid = (x + y)/2;            query(x, mid, nu*2);            query(mid +1, y, nu*2 + 1);    }}int main(){   scanf("%d", &T);   while(T--)   {       memset(Tree, 0, sizeof(Tree));       memset(num, 0, sizeof(num));       memset(post, 0, sizeof(post));        memset(num2, 0, sizeof(num2));        memset(vist, 0, sizeof(vist));        ans = 0;       scanf("%d", &n);       int k = 0;       for(int i = 1; i <= n; i++)       {           scanf("%d%d", &post[i][0], &post[i][1]);           num[++k] = post[i][0];           num[++k] = post[i][1];       }       sort(num + 1, num + k + 1);       k = unique(num + 1, num + k + 1) - num;       k = k - 1;       int kn = 0;       for(int i = 1; i <= k; i++)//离散化;       {           if(i > 1 && num[i] > num[i-1] + 1)           {               num2[++kn] = num[i-1] + 1;           }           num2[++kn] = num[i];       }       Make_Tree(1, kn, 1);       int xn, yn;       for(int i = 1; i <= n; i++)       {           xn = Find(1, kn, post[i][0]);           yn = Find(1, kn, post[i][1]);           Add(xn, yn, i, 1);       }       query(1, kn, 1);       printf("%d\n", ans);   }    return 0;}


原创粉丝点击