poj 2352

来源:互联网 发布:恒鸿达软件 编辑:程序博客网 时间:2024/06/06 01:01

         题目的意思是要算出每个节点的左方和下方共有多少个节点,由于题目当中节点的顺序是按x与y的升序给出的,所以只需按照输入顺序逐个处理节点即可。

         对于每一个未处理的节点,每个已处理的节点必然在它的下侧或者左侧,所以在处理每一个节点时,只需要考虑该节点的左边有多少已处理的节点即可。用数学化的表示方法即是对于待处理节点(x, y),找出(0, x)内有多少个已处理的节点。

         此题可以用两种方法,一是线段树,二是树状树组,其时间复杂度均为O(nlogn),不过树状树组的空间复杂度较小,而且代码实现上也比较简单。不过使用树状树组时需要注意,由于树状树组是由1开始计数的,而本题的坐标可以为0,所以再使用树状树组时,需要把每个点的横坐标平移一位。

         树状数组的lowbit操作虽然功能简单,但是是一个频繁调用的操作,所以如果不写在函数里,而是直接使用x += x & (-x)或x -= x & (-x)效率会提高不少。

 

方法一:

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

 

const int MAX_LEN = 32000;

const int MAXN = 65000;

const int MAXSTAR = 15000;

 

struct TreeNode {

         intl, r;

         intnum;  

};

 

TreeNode tree[MAXN];

 

void makeTree(int st, int end, int treeNum){

         tree[treeNum].l= st;

         tree[treeNum].r= end;

         tree[treeNum].num= 0;

         if(end - st >= 1) {

                   intmid = (st + end) / 2;

                   makeTree(st,mid, treeNum * 2);

                   makeTree(mid+ 1, end, treeNum * 2 + 1);

         }       

         return;

}

 

void insertTree(int x, int treeNum) {

                   tree[treeNum].num++;

                   if(tree[treeNum].l == tree[treeNum].r) {

                            return;

                   }

                   intmid = (tree[treeNum].l + tree[treeNum].r) / 2;

                   if(x <= mid) {

                            insertTree(x,treeNum * 2);

                   }else {

                            insertTree(x,treeNum * 2 + 1);      

                   }                          

         return;

}

 

int searchTree(int st, int end, inttreeNum) {

         intiRes = 0;

         intiMid;

         TreeNode&i = tree[treeNum];

         iMid= (i.l + i.r) / 2;

         if(i.l == st && i.r == end) {

                   iRes= i.num;

         }else {

                   if(end <= iMid) {

                            iRes+= searchTree(st, end, treeNum * 2);

                   }else if (st > iMid) {

                            iRes+= searchTree(st, end, treeNum * 2 + 1);

                   }else {

                            iRes+= searchTree(st, iMid, treeNum * 2);

                            iRes+= searchTree(iMid + 1, end, treeNum * 2 + 1);              

                   }

         }

         returniRes;

}

 

int main(void) {

         intn;

         intlevel[MAXSTAR];

         intiRes;

         scanf("%d",&n);

         intx, y;

         makeTree(0,MAX_LEN, 1);

         memset(level,0, sizeof(level));

         for(int i = 1; i <= n; i++) {

                   scanf("%d%d",&x, &y);

                   iRes= searchTree(0, x, 1);

                   insertTree(x,1);

                   level[iRes]++;

         }

         for(int i = 0; i < n; i++) {

                   printf("%d\n",level[i]);

         }

         return0;

}

 

方法二:

#include <iostream>

#include <cstdio>

#include <cstring>

 

using namespace std;

 

const int MAXN = 32010;

const int MAXN2 = 15010;

 

int tree[MAXN];

int level[MAXN2];

 

int lowbit(int x) {

         returnx & (x ^ (x - 1));

}

 

int calSum(int x) {

         intiAns;

         iAns= 0;

         for(int i = x; i > 0; i -= lowbit(i)) {

                   iAns+= tree[i];

         }

         returniAns;

}

 

void updateTree(int x) {

         for(int i = x; i <= MAXN; i += lowbit(i)) {

                   tree[i]++;

         }

         return;

}

 

int main(void) {

         intn;

         intx, y;

         scanf("%d",&n);

         memset(tree,0, sizeof(tree));

         memset(level,0, sizeof(level));

         for(int i = 0; i < n; i++) {

                   scanf("%d%d",&x, &y);

                   x++;

                   level[calSum(x)]++;

                   updateTree(x);

         }

         for(int i = 0; i < n; i++) {

                   printf("%d\n",level[i]);

         }

         return0;          

}

原创粉丝点击