线段树

线段树的存储结构:


线段树的实现:

typedef struct node
{
int  ld,rd;
struct  node  *lc, *rc;
keytype  key;
} node;

建空树:

node* buildtree( int a, int b )
{
node* p = { 给p申请一块内存}
p -> ld = a; p -> rd = b;
{初始化p->key}
if ( a == b ) return p;
p -> lc = buildtree( a, ( a + b ) / 2 );
p -> rc = buildtree( ( a + b ) / 2 + 1, b );
return p;
}

插入线段:

void insert( node *T, int a, int b, keytype key )
{
if ( a <= T -> ld && T -> rd <= b )
{根据key处理T->key; return; }
if ( a <= ( T -> ld + T -> rd ) / 2 )
insert( T -> lc, a, b, key );
if ( b > ( T -> ld + T -> rd ) / 2 )
insert( T -> rc, a, b, key );
{根据T->lc和T->rc的信息处理T->key}
}

查找线段[a,b]的key值

keytype search( node *T, int a, int b )
{
keytype res;
if ( a <= T -> ld && T -> rd <= b )
{根据T -> key处理res; return res; }
if ( a <= ( T -> ld + T -> rd ) / 2 )
{根据search( T -> lc, a, b )处理res}
if ( b > ( T -> ld + T -> rd ) / 2 )
{根据search( T -> rc, a, b )处理res}
return res;
}

对于线段树,用数组来模拟指针对于计算机实现比较快,可能与cache预测相关。

jobdu1496:

#include <stdio.h>
#include <string.h>
  
#define INVALID -1
  
typedef struct _node
{
    int lb;
    int rb;
    int key;
} Node;
  
typedef struct _sq
{
    int left;
    int right;
    int key;
} Sq;
  
Sq sq[100006];
Node node[3000006];
  
int node_ind;
int sq_ind;
int n, m;
  
void buildtree(int l, int r, int index)
{
    node[index].lb = l;
	node[index].rb = r;
    node[index].key = 0;
    if (l != r)
    {
        buildtree(l, (l+r)>>1, index<<1);
        buildtree(1+((l+r)>>1), r, 1+(index<<1));
    }
}
  
void insert(int index, int l, int r, int key)
{
	int mid;
	if (l<=node[index].lb && r>=node[index].rb) /* 插入的范围覆盖整个区间 */
    { node[index].key = key; }
    else {  /* 不覆盖整个区间 */
        if (node[index].key > 0)
        {
			node[index<<1].key = node[index].key;
            node[1+(index<<1)].key = node[index].key;
        }
        node[index].key = INVALID; /* 当前这段的key值 无效*/
		mid = (node[index].lb+node[index].rb)>>1;
        if (l <= mid)
        { insert(index<<1, l, r, key); } /* 和左区间重叠 */
           
          
        if (r > mid) /* 和右区间重叠 */
        { insert(1+(index<<1), l, r, key); }  
          
    }
}
  
void search(int index)
{
    if (node[index].key == INVALID)
    {
        search(index<<1);
        search(1+(index<<1));
    } else if (node[index].key != 0) {
        sq[sq_ind].left = node[index].lb;
        sq[sq_ind].right = node[index].rb;
        sq[sq_ind++].key = node[index].key;
    }
}

int main(void)
{
    int i;
    int left, right;
    int maxcnt, count;
    while(scanf("%d%d", &n, &m) !=EOF)
    {
        node_ind = 0;
        buildtree(1, n, 1);
        for (i=1; i<=m; i++)
        {
            scanf("%d%d", &left, &right);
            insert(1, left, right, i);
        }
        sq[0].right = sq[0].right = sq_ind = 0;
        search(1);
        count = maxcnt = sq[0].right - sq[0].left + 1;
        for (i=1; i<sq_ind; i++)
        {
            count = count * (sq[i].key == sq[i-1].key) + sq[i].right - sq[i].left + 1;
            maxcnt = count > maxcnt ? count : maxcnt;
        }
        printf("%d\n", maxcnt);
    }
    return 0;
}


答案没用用线段树写得非常好!!!

#include <stdio.h>
int next[1000010];
int a[1000010];
struct E {
        int l;
        int r;
}list[100010];
int main () {
        int n ,m;
        while (scanf ("%d%d",&n,&m) == 2) {
                for (int i = 1;i <= n;i ++) {
                        a[i] = 0;
                        next[i] = i + 1;
                }
                for (int i = 1;i <= m;i ++) {
                        scanf ("%d%d",&list[i].l,&list[i].r);
                }
                for (int j = m;j >= 1;j --) {
                        int l = list[j].l, r = list[j].r;
                        for (int i = l;i <= r;) {
                                if (a[i] == 0) {
                                        a[i] = j;
                                }
                                int tmp = next[i];
                                next[i] = next[r]>tmp ? next[r]:tmp;
                                i = tmp;
                        }
                }
                int ans = 0;
                int cnt = 0;
                for (int i = 1;i <= n;i ++) {
                        if (a[i] == 0 || i != 1 && a[i] != a[i - 1]) {
                                if (cnt > ans) {
                                        ans = cnt;
                                }
                                if (a[i] != 0)
                                        cnt = 1;
                                else
                                        cnt = 0;
                        }
                        else cnt ++;
                }
                if (cnt > ans)
                        ans = cnt; 
                printf("%d\n",ans);
        }
        return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值