這個題的線段樹倒還沒有特別難,只是想到如何去用這個線段樹比較麻煩。這裏我們動態地想象這整個過程,當豎線在最左邊時,對於某個橫線,大於線的縱座標,就是第一象限,就是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);
}
};