题目链接:http://poj.org/problem?id=2481
我感觉这道题给那个那个差的比较就是坑爹的……我按着差写了大半天结果WA了个各种惨啊……
好吧,这道题是按照权值建立线段树,意思就是把每一个点加入到它应有的大小范围内,线段树上面每一个点维护的是该区间内有多少个点,这样很容易就能查出来比某一个元素大的元素有多少个。而且,还得先对所有的点排序,主排序应该是把s从小到大排序,当s相等的时候,e从大到小排序,这样就必须记录每个元素原来的位置,这样每次插入一个新的元素的时候,在它之前插入的所有的元素s上都是满足条件的,换言之,线段树中只需要维护e的情况就行了。其实……e符合条件了差值自然也就符合条件了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 100100;
struct data{
int s, e, i;
friend bool operator < (const data &a, const data &b){
if (a.s != b.s) return a.s < b.s;
return a.e > b.e;
}
}cow[maxn];
int num[maxn << 2], ans[maxn];
void build(int l, int r, int rt){
num[rt] = 0;
if (l == r) return;
int m = (l + r) >> 1;
build(lson);
build(rson);
}
void update(int x, int l, int r, int rt){
num[rt] += 1;
if (l == r) return;
int m = (l + r) >> 1;
if (x <= m) update(x, lson);
else update(x, rson);
}
int query(int ll, int rr, int l, int r, int rt){
if (ll <= l && rr >= r) return num[rt];
int m = (l + r) >> 1;
int ret = 0;
if (ll <= m) ret += query(ll, rr, lson);
if (rr > m) ret += query(ll, rr, rson);
return ret;
}
int main(){
int n;
while (~scanf("%d", &n) && n){
memset(ans, 0, sizeof(ans));
int m = 0;
for (int i = 0; i < n; i++){
scanf("%d%d", &cow[i].s, &cow[i].e);
cow[i].s += 1; cow[i].e += 1;
m = max(cow[i].e, m);
cow[i].i = i;
}
sort(cow, cow + n);
build (1, m, 1);
for (int i = 0; i < n; i++){
if (i && cow[i].s == cow[i - 1].s && cow[i].e == cow[i - 1].e){
ans[cow[i].i] = ans[cow[i - 1].i];
update(cow[i].e, 1, m, 1);
}
else{
ans[cow[i].i] = query(cow[i].e, m, 1, m, 1);
update(cow[i].e, 1, m, 1);
}
}
for (int i = 0; i < n; i++){
printf("%d", ans[i]);
if (i != n-1) printf(" ");
else printf("\n");
}
}
return 0;
}
本文介绍了一种使用线段树解决特定查询问题的方法。通过建立线段树并维护区间内的点数,可以高效地查询比某个元素大的元素数量。文章详细解释了排序和更新线段树的过程,并提供了完整的代码实现。
1478

被折叠的 条评论
为什么被折叠?



