线段树入门 以HDU 4325为例(未离散化,也没lazy标记)

今天都是看的线段树,终于自己能编出简单的来了,虽然还没弄明天离散化,但是先放着,怕文件丢了,先上传再说。

在睡前终于把代码都敲出没有问题出来了,哎哟,累了一天了,继续努力,争取这两天把离散化也学会了!!!

未离散化,也没lazy标记,所以只有在数据比较少的时候才能通过,不然就TLE了。离散化和lazy标记提交通过的代码在下下章!


下面是入门敲的代码,一点一点把线段树的本质搞定。弄明白了线段树是怎么运作的。

#include <iostream>
#include <map>
#include <deque>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
int INF=1<<30;
const int m=100000;    //本来不想离散化了,自己也还没搞定明白离散化,所以相把m开到10^9,但是太大了不行,所以还是学离散化吧
struct node
{
    int a,b,sum;
}tree[m*5];
void build(int now,int a,int b)
{
    tree[now].a=a;
    tree[now].b=b;
    tree[now].sum=0;    //建立完全二叉树,因为每个点可能都要用得到,其实理解最好的方法是看图再理解代码最快
    if(a==b) return;
    int mid=(a+b)>>1;
    build(now*2,a,mid);
    build(now*2+1,mid+1,b);
}
void update(int i,int a,int b)
{
    if(tree[i].a==a&&tree[i].b==b)
    {
        tree[i].sum++;
        if(tree[i].a==tree[i].b) return;
        update(i*2,a,(a+b)/2);   //找到这条线段之后,这条线段以下的所以儿子都要更新,以使最后的点有,我设这个点为(x,x)即左右端点都相等表示这个点
        update(i*2+1,(a+b)/2+1,b);
        return;
    }
    int mid=(tree[i].a+tree[i].b)/2;
    if(a<=mid) update(i*2,a,min(mid,b));   //找到这条线段为此
    if(b>mid) update(i*2+1,max(a,mid+1),b);
}
int query(int i,int x)
{
    int mid=(tree[i].a+tree[i].b)>>1;
    if(tree[i].a==x&&tree[i].b==x) return tree[i].sum;   //上面说过,左右端点相等表示这个点
    if(x<=mid) return query(i*2,x);
    else return query(i*2+1,x);
}
int main()
{
    int t,p,k=1,n,m,i,c,d;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(1,1,10000);   //建树
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&c,&d);
            update(1,c,d);    //更新树
        }
        printf("Case #%d:\n",k++);
        for(i=0;i<m;i++)
        {
            scanf("%d",&p);
            printf("%d\n",query(1,p));  //查询
        }
    }
    return 0;
}

你可能感兴趣的:(线段树入门 以HDU 4325为例(未离散化,也没lazy标记))