poj 2828 Buy Tickets(線分木単点更新)
1490 ワード
http://poj.org/problem?id=2828
タイトル:
n人がいて、一人一人がvalueに対応して、それらは順番に自分が挿入したい位置(0から)に挿入して、最後のキューの状態がどのようなものかを聞きます.
題意を読んだ後、線分樹でどうするか思いもよらず、単点更新しか知らなかった.人の考えを見て、線分の木に逆順に挿入すべきだと分かった.最後の人は必ずその位置にいることができるので、オンラインセグメントツリーでその位置を見つけて削除します.つまり、最後から2番目の人の位置選択は最後の人の位置とは関係なく、一人一人の最後の位置を確定することができます.最後の人まで操作を繰り返します.
線分ツリーで特定の人の位置が単一の更新と類似している場合、1つの区間内で削除されていない(すなわち無視されていない)数字の個数を現在探している位置posと比較し、posが小さい場合は左の区間を更新し、そうでない場合は右の区間を更新します.
この問題はpoj 2182と似ています.
タイトル:
n人がいて、一人一人がvalueに対応して、それらは順番に自分が挿入したい位置(0から)に挿入して、最後のキューの状態がどのようなものかを聞きます.
題意を読んだ後、線分樹でどうするか思いもよらず、単点更新しか知らなかった.人の考えを見て、線分の木に逆順に挿入すべきだと分かった.最後の人は必ずその位置にいることができるので、オンラインセグメントツリーでその位置を見つけて削除します.つまり、最後から2番目の人の位置選択は最後の人の位置とは関係なく、一人一人の最後の位置を確定することができます.最後の人まで操作を繰り返します.
線分ツリーで特定の人の位置が単一の更新と類似している場合、1つの区間内で削除されていない(すなわち無視されていない)数字の個数を現在探している位置posと比較し、posが小さい場合は左の区間を更新し、そうでない場合は右の区間を更新します.
この問題はpoj 2182と似ています.
#include <stdio.h>
#include <string.h>
const int maxn = 200001;
struct line
{
int l;
int r;
int len;//
}tree[4*maxn];
int n;
int ans[maxn];
//
void build(int v, int l, int r)
{
tree[v].l = l;
tree[v].r = r;
tree[v].len = r-l+1;
if(l == r) return;
int mid = (l+r)>>1;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
}
void update(int v, int posi, int vali)
{
tree[v].len--;// 1, posi
if(tree[v].l == tree[v].r)
{
ans[tree[v].l] = vali;
return;
}
if(posi < tree[v*2].len)
update(v*2,posi,vali);
else update(v*2+1,posi - tree[v*2].len,vali);
}
int main()
{
int pos[maxn],val[maxn];
while(~scanf("%d",&n))
{
build(1,0,n-1);
for(int i = 0; i < n; i++)
scanf("%d %d",&pos[i],&val[i]);
for(int i = n-1; i >= 0; i--) //
{
update(1,pos[i],val[i]);
}
for(int i = 0; i < n-1; i++)
printf("%d ",ans[i]);
printf("%d
",ans[n-1]);
}
return 0;
}