pku 2481 Cows(预处理,树状数组)

给定n个区间(l,r),问每个区间被多少个另外的区间所包含。

包含的定义(l1,r1),(l2,r2),如果l1<=l2<r2<=r1&&(l1,r1)!=(l2,r2),则(l1,r1)包含(l2,r2)。

 

用节点存储区间,然后给节点排序。l小的区间放在前面,l相同则r大的区间放在前面。

为什么这样排序呢?因为对排序之后的节点,节点n只可能被排在它前面的(0--n-1)号节点包含,而不可能被后面的包含。

那么(0--n-1)号节点中,又哪些能包含节点n呢?只要ri>=rn即可。(因为li<=ln的)。

至于那部分怎么统计,用树状数组可以达到lgn的效率。

#include <algorithm> #include <iostream> using namespace std; const int maxn=100000; struct node { int l,r; int id; }nodes[maxn+20]; int tree[maxn+10]; int lowbit(int n) { return n&(n^(n-1)); } void insert(int n) { while(n<=maxn+10) { tree[n]++; n=n+lowbit(n); } } int query(int n) { int ans=0; while(n>0) { ans+=tree[n]; n=n-lowbit(n); } return ans; } bool operator<(const node p1,const node p2) { if(p1.l==p2.l) return p1.r>p2.r; else return p1.l<p2.l; } int ans[maxn+20]; int main() { int n; while(scanf("%d",&n)&&n) { memset(ans,0,sizeof(ans)); memset(tree,0,sizeof(tree)); for(int i=0;i<n;i++) { scanf("%d%d",&nodes[i].l,&nodes[i].r); nodes[i].id=i; } sort(nodes,nodes+n); ans[nodes[0].id]=0; insert(nodes[0].r); int cnt=0; for(int i=1;i<n;i++) { if(nodes[i].l==nodes[i-1].l&&nodes[i].r==nodes[i-1].r) cnt++; else cnt=0; ans[nodes[i].id]=i-cnt-query(nodes[i].r-1); insert(nodes[i].r); } printf("%d",ans[0]); for(int i=1;i<n;i++) printf(" %d",ans[i]); printf("/n"); } return 0; }

你可能感兴趣的:(pku 2481 Cows(预处理,树状数组))