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

来源:互联网 发布:注册域名要钱吗 编辑:程序博客网 时间:2024/05/18 03:05

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

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

未离散化,也没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;}

原创粉丝点击