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);
    }
};

 

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