POJ 2481 树状数组(Binary Indexed Tree)

题意:
    求每个线段被其它线段完全覆盖的条数(不包括完全重合的)
思路:
    1、将线段s,t变成正交坐标系的x,y,则即为求每条线段的左上角的线段的条数,我将所有的y变成负的,就是求左下角的。
     2、将线段先按y从小到大排,y相同,则x从小到大排。
    3、用数状数组记录x坐标上的点的个数,然后一个个的统计当前点x的左边点的个数,同时一个一个插入数状数组。

#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN=100001; struct cnode { int x; int y; int num; }node[MAXN+10]; int ans[MAXN+10]; bool cmp(const cnode &e1,const cnode &e2) { if(e1.y!=e2.y) { return e1.y<e2.y? true:false; } else { return e1.x<e2.x? true:false; } } int tree[MAXN+10];//树状数组 int sum(int x)//求和 { int value=0; // x-=(x&(x^(x-1))); while(x>0) { value+=tree[x]; x-=(x&(x^(x-1))); } return value; } void insert(int x)//插入点 { while(x<=MAXN) { tree[x]++; x+=(x&(x^(x-1))); } } int main() { int n; int i; while(scanf("%d",&n)!=EOF) { if(n==0) { break; } memset(tree,0,sizeof(tree)); // memset(ans,0,sizeof(ans)); for(i=0;i<n;i++) { scanf("%d %d",&node[i].x,&node[i].y); node[i].num=i; node[i].y=-node[i].y; node[i].x++; } sort(&node[0],&node[n],cmp); for(i=0;i<n;i++) { if(i!=0) { if(node[i].x==node[i-1].x&&node[i].y==node[i-1].y)//完全重合的不统计 { ans[node[i].num]=ans[node[i-1].num]; } else { ans[node[i].num]=sum(node[i].x); } } else { ans[node[i].num]=sum(node[i].x); } insert(node[i].x); } for(i=0;i<n;i++) { printf("%d ",ans[i]); } printf("/n"); } return 0; }

你可能感兴趣的:(struct,tree,ini,insert)