链接:
http://poj.org/problem?id=2481
题目大意:
给n个区间,对于两个区间【Si,Ei】和【Sj, Ej】,如果Si <= Sj 且Ej <= Ei 且Ei - Si > Ej - Sj, 就说区间i比区间j“强大”。也就是区间i要严格包含区间j。
求每个区间i,有多少个区间比i“强大”,并输出。
分析与总结:
昨天的CF的B题Big Segment也是和这题的区间包含的处理相似,先把输入的所有边进行排序,先按S从小到大排序,如果S相同的,就按照E从大到小的顺序排序。
排序之后,可以观察发现,对于第i条边,它之前的所有边j全都满足Ej <= Ei,所以对于i边,只需要计算它之前所有边的Ej>=Ei的边数,就是所有比i边“强大”的数量。
但是有一个特殊情况要特判,就是如果i边的前一条边和i完全相同,那么i边的数量就直接和i-1边相同。
用线段树或树状数组处理所有边的E点。
1. 树状数组
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 100005;
int c[MAXN], n;
int ans[MAXN];
struct node{
int beg,end;
int id;
friend bool operator<(const node&a,const node&b){
if(a.beg != b.beg) return a.beg < b.beg;
return a.end > b.end;
}
}arr[MAXN];
void init(){
memset(c, 0, sizeof(c));
memset(ans, 0, sizeof(ans));
}
int lowbit(int x){ return x&(-x);}
void add(int x){
while(x<MAXN){
++c[x];
x += lowbit(x);
}
}
int sum(int x){
int ret=0;
while(x > 0){
ret += c[x];
x -= lowbit(x);
}
return ret;
}
int main(){
int S,E;
while(scanf("%d",&n) && n) {
init();
for(int i=0; i<n; ++i) {
scanf("%d%d",&arr[i].beg, &arr[i].end) ;
++arr[i].beg;
++arr[i].end;
arr[i].id = i;
}
sort(arr, arr+n);
for(int i=0; i<n; ++i){
if(i && arr[i].beg==arr[i-1].beg && arr[i].end==arr[i-1].end){
ans[arr[i].id] = ans[arr[i-1].id];
add(arr[i].end);
}
else{
ans[arr[i].id] = sum(MAXN-1)-sum(arr[i].end-1);
add(arr[i].end);
}
}
for(int i=0; i<n; ++i)
if(i) printf(" %d",ans[i]);
else printf("%d",ans[i]);
puts("");
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((left+right)>>1)
#define lson rt<<1,left,mid
#define rson rt<<1|1,mid+1,right
using namespace std;
const int MAXN = 100005;
int sum[MAXN<<2], n;
int ans[MAXN];
struct node{
int beg,end;
int id;
friend bool operator<(const node&a,const node&b){
if(a.beg != b.beg) return a.beg < b.beg;
return a.end > b.end;
}
}arr[MAXN];
void init(){
memset(sum, 0, sizeof(sum));
memset(ans, 0, sizeof(ans));
}
void update(int rt,int left,int right,int data){
++sum[rt];
if(left==right) return ;
if(data <= mid) update(lson,data);
else update(rson,data);
}
int query(int rt,int left,int right,int l,int r){
if(left==l && right==r) return sum[rt];
int m = mid;
if(r <= m) return query(lson,l,r);
else if(l > m) return query(rson,l,r);
else return query(lson,l,m)+query(rson,m+1,r);
}
int main(){
int S,E;
while(scanf("%d",&n) && n) {
init();
int N=0;
for(int i=0; i<n; ++i) {
scanf("%d%d",&arr[i].beg, &arr[i].end) ;
++arr[i].beg;
++arr[i].end;
if(arr[i].end > N) N=arr[i].end;
arr[i].id = i;
}
sort(arr, arr+n);
for(int i=0; i<n; ++i){
if(i && arr[i].beg==arr[i-1].beg && arr[i].end==arr[i-1].end){
ans[arr[i].id] = ans[arr[i-1].id];
update(1,1,N,arr[i].end);
}
else{
ans[arr[i].id] = query(1,1,N,arr[i].end,N);
update(1,1,N,arr[i].end);
}
}
for(int i=0; i<n; ++i)
if(i) printf(" %d",ans[i]);
else printf("%d",ans[i]);
puts("");
}
return 0;
}
—— 生命的意义,在于赋予它意义士。
原创 http://blog.csdn.net/shuangde800 , By D_Double (转载请标明)