HDU 1156 Brownie Points II 思维+线段树+离散化

这个题的线段树倒还没有特别难,只是想到如何去用这个线段树比较麻烦。这里我们动态地想象这整个过程,当竖线在最左边时,对于某个横线,大于线的纵座标,就是第一象限,就是st的得分;小于这个纵座标,就是第四象限,就是ol的得分。我们把每个点的这两个值都用线段树记下来。然后,处理这个竖线上的点。当我们把竖线朝右移的时候,一个原竖线上的点,对于高于它的点,将变成第三象限的点,我们更新记录高于它的点的st的得分。而对于低于它的点,我们更新ol的得分。这样,我们把可能的竖线都处理完,所有的点就都被遍历了一遍。

平生第二次手写线段树,果不其然写错了哩。照着人家的题解改了一遍才过。

struct segment_tree{
    int x,y;
    void pushdown(int rt)
    {
        tree[rt*2].flag[0]+=tree[rt].flag[0];
        tree[rt*2+1].flag[0]+=tree[rt].flag[0];
        tree[rt*2].flag[1]+=tree[rt].flag[1];
        tree[rt*2+1].flag[1]+=tree[rt].flag[1];
        tree[rt].flag[0]=0; tree[rt].flag[1]=0;
        return;
    }
    void build(int l,int r,int rt)
    {
        //cout<<"l="<<l<<" r="<<r<<" rt="<<rt<<endl;
        tree[rt].flag[0]=0;
        tree[rt].flag[1]=0;
        if (l==r)
        {
            tree[rt].flag[0]=st[l];
            tree[rt].flag[1]=ol[l];
            return;
        }
        int mid=l+r>>1;
        build(l,mid,rt*2);
        build(mid+1,r,rt*2+1);
        return;
    }
    void update(int l,int r,int rt,int type,int d)
    {
        //cout<<"l="<<l<<" r="<<r<<" x="<<x<<" y="<<y<<endl;
        if (l>=x && r<=y)
        {
            tree[rt].flag[type]+=d;
            return;
        }
        pushdown(rt);
        int mid=l+r>>1;
        if (mid>=x)
        {
            update(l,mid,rt*2,type,d);
        }
        if (mid<y)
        {
            update(mid+1,r,rt*2+1,type,d);
        }
    }
    void query(int l,int r,int &mi, int &mx, int rt,int pos)
    {
        if (l==r)
        {
            mi=tree[rt].flag[0];
            mx=tree[rt].flag[1];
            return;
        }
        pushdown(rt);
        int mid=l+r>>1;
        if (pos<=mid) query(l,mid,mi,mx,rt*2,pos);
        else query(mid+1,r,mi,mx,rt*2+1,pos);
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章