感悟线段树
其实线段树的数据结构没什么可说的,但是怎么用好它就有得说了。
具体的来说就是:
首先就是有段关系了,这个是第一位的。
接着就是有大小关系了,这个是第二位的。
再者就是数据量大,这个是次要的。
只要满足了这三个条件,就是用线段树的时候了。
如何理解段呢?比如说让你统计小于200的数据有多少个。这个就是段了。
至于大小就是小于200的200了。
(1)1 3 2 4 5 63 563 23 46 56 23 455 …… 888 这个例子是落在888以前的。
(2)当然还是段中段,这个就不解释了。
下面来贴出一道相关的题目。
http://acm.swust.edu.cn/oj/contest/29/825/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include "iostream"
#include "cstdio"
#include "cstring"
#include "string"
#include "algorithm"
using namespace std;
#define Maxn 100005
struct Animals
{
int s, v;
bool Flag;
};
Animals RT[Maxn*2];
bool Cmp(Animals a, Animals b)
{
return (a.s<b.s);
}
struct Node
{
int Left, Right, Sum;
};
Node Tree[Maxn*4];
void BTree(int x, int y, int p)
{
Tree[p].Left = x;
Tree[p].Right = y;
Tree[p].Sum = 0;
if(x<y)
{
int Mid = (x+y)/2;
BTree(x, Mid, p<<1); //2*p
BTree(Mid+1, y, p<<1|1); //2*p+1 //mid+1哈,不然stack overflow
}
}
void Add(int x, int p)
{
if(Tree[p].Left==Tree[p].Right && Tree[p].Left==x)
{
Tree[p].Sum=(Tree[p].Sum+1)%2012;
return;
}
int Mid=(Tree[p].Left+Tree[p].Right)/2;
if(x<=Mid) Add(x, p<<1);
else Add(x, p<<1|1);
Tree[p].Sum = (Tree[p<<1].Sum+Tree[p<<1|1].Sum)%2012;
}
long long Query(int x, int y, int p)
{
if(Tree[p].Left==x && Tree[p].Right==y) return Tree[p].Sum;
int Mid = (Tree[p].Left+Tree[p].Right)/2;
if(y<=Mid) return Query(x, y, p<<1);
else if(x>=Mid+1) return Query(x, y, p<<1|1);
else return (Query(x, Mid, p<<1)+Query(Mid+1, y, p<<1|1))%2012;
}
int N;
int main()
{
int Max=0;
while(scanf("%d", &N)!=EOF)
{
for(int i=0; i<N; i++)
{
scanf("%d%d", &RT[i].s, &RT[i].v);
RT[i].Flag = true;
Max = max(Max, RT[i].v);
}
for(int i=N; i<2*N; i++)
{
scanf("%d%d", &RT[i].s, &RT[i].v);
RT[i].Flag = false;
Max = max(Max, RT[i].v);
}
sort(RT, RT+2*N, Cmp);
BTree(1, Max, 1);
int Ans = 0;
for(int i=0; i<2*N; i++)
{
if(RT[i].Flag)
{
if(RT[i].v==Max) continue;
Ans=(Ans+Query(RT[i].v+1, Max, 1))%2012;
}
else Add(RT[i].v, 1);
}
printf("%d\n", Ans);
}
}
posted on 2012-03-31 22:44 More study needed. 阅读(300) 评论(0) 编辑 收藏 举报