POJ2828 Buy Tickets 線段樹好題


POJ2828 Buy Tickets

題意:插隊問題;

關鍵:如何插入這幾個節點,每個節點儲存什么信息。

類型:很基本的單點更新線段樹

思路:這題想到了就水了,數據逆着插入,最先插入的一個數據的位置明顯是題目給定的位置,可以確定,然后插入的幾個數根據的位置前面插入的數據來決定,

用sum[]數組表示改線段空位置的個數,滿足 pos<=sum[rt<<1](即左兒子的空位多於插入數的位置序號)就訪問左兒子,否則訪問右兒子

(訪問右節點的時候注意pos要修改,改為pos-sum[rt],即整個線段的第pos個空位,在下一個右兒子那的第pos-sum[rt]個空位)。
對自己的總結: 剛學線段樹,誒,這題刷了一下午,看來線段樹的基礎還不夠,要加油了;

下面是我的AC代碼。

View Code
#include<stdio.h>
#include<string.h>

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mid int m = (l + r)>>1
#define maxn 200000

int sum[maxn<<2],pos[maxn],val[maxn],ans[maxn<<2];//ans儲存插入的值;

void push_up(int rt)
{
    sum [rt] = sum[rt<<1]+sum[rt<<1|1];
}
void build(int l, int r, int rt)
{
    sum[rt]=r-l+1;
    if(l == r)return;
    mid;
    build(lson);
    build(rson);
}
void update(int pos, int val, int l, int r, int rt)
{
    if(l == r){ans[rt]=val;sum[rt]--;return;}
    mid;
    if(pos <= sum[rt<<1])update(pos, val, lson); //根據左右兒子空位的多少和插入數據的位置比較來確定插入哪個兒子
    else update(pos -sum[rt<<1], val, rson);
    push_up(rt);
}
void print(int l, int r, int rt)
{
    if(l == r){printf("%d ",ans[rt]);return;}
    mid;
    print(lson);
    print(rson);
}
int main()
{
    int n,i;
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)
            scanf("%d%d",&pos[i],&val[i]);
        build(1, n ,1);
        for(i=n-1;i>=0;i--)
            update(pos[i]+1, val[i], 1, n, 1);
        print(1, n, 1);
        printf("\n");
    }
    return 0;
}

還有一種是節點記錄已占有的位置(即非空位),cnt[rt]+pos<=m訪問左節點,否則就訪問右兒子(訪問右兒子時節點修改為cnt[rt]+pos);

View Code
#include<stdio.h>
#include<string.h>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mid int m = (l + r)>>1
#define maxn 200000
int cnt[maxn<<2],ans[maxn<<2],pos[maxn],val[maxn];
void update(int pos, int val, int l, int r, int rt)
{
    cnt[rt]++;
    if(l == r){ans[rt]=val;return;}
    mid;
    if(pos + cnt[rt<<1] <= m)update(pos, val, lson);
    else update(pos+cnt[rt<<1], val, rson);
}
void print(int l, int r, int rt)
{
    if(l == r){printf("%d ",ans[rt]);return;}
    mid;
    print(lson);
    print(rson);
}
int main()
{
    int n,i;
    while(~scanf("%d",&n))
    {
        memset(cnt,0,sizeof(cnt));
        for(i=0;i<n;i++)
            scanf("%d%d",&pos[i],&val[i]);
        for(i=n-1;i>=0;i--)
        {
            update(pos[i]+1, val[i], 1, n, 1);
        }
        print(1, n, 1);
        printf("\n");
    }
    return 0;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM