NOI2004 鬱悶的出納員

2022-05-20 16:01:36 字數 1633 閱讀 5731

題目大意:

給定$n(n\leq100000)$和$min$,按照給定的順序進行以下操作共$n$次:

1.加入乙個數;

2.把所有數加上$x$;

3.把所有數減去$x$,並把小於$min$的數刪去;

4.詢問第$k$大數。

思路:splay。區間加減可以用tag實現,刪數可以通過把大於等於$min$的最小數提到根,然後刪除左子樹。

1 #include2 #include3 #include4 inline int

getint()

11 inline char

getalpha()

16const

int n=100001;17

intext;

18class

splaytree

26void push_up(const

int &p)

29void push_down(const

int &p)

34if(ch[p][1

]) 38 tag[p]=0;39

}40void rotate(const

int &x)

48void splay(int x,const

int &goal)

52if(!goal) root=x;53}

54public:55

splaytree()

58void insert(const

int &x)

64push_down(y);

65 par[ch[y][x>val[y]]=new_node(x)]=y;

66 splay(y,0

);67 cnt++;68}

69void modify(const

int &x)

73void erase(const

int &min)

79if(!tmp) return

;80 splay(tmp,0

);81

if(!ch[tmp][0]) return

;82 ext+=size[ch[tmp][0

]];83 size[tmp]-=size[ch[tmp][0

]];84 cnt-=size[ch[tmp][0

]];85 ch[tmp][0]=0;86

}87int find(int

x) 94}95

};96

splaytree t;

97int

main()

104if(opt=='a'

) t.modify(x);

105if(opt=='s'

) 109

if(opt=='

f') printf("

%d\n

",t.find(x));

110}

111 printf("

%d\n

",ext);

112return0;

113 }

noi 2004 鬱悶的出納員

原題位址 花了一兩天真正的熟悉了treap,對於乙個東西,本蒟蒻認為,不應該要會,還應會熟練的寫,像哈狗寫這個只需十分鐘 好吧,話歸正題 先推薦另類解法 戳進去 此題解法很多bit 權值線段樹 各種平衡樹 準備抽空寫 是一道很棒的模板題。這道題我們把每次全體加的工資和減的弄到乙個變數,姑且叫為w,把...

NOI2004 鬱悶的出納員

大致題意就是對初始為空的數列的各種操作233 題解 splay啦 其中可能會遇到的幾個問題 1.如何刪去低於min的點 找到數列中min的後繼提為根,把根的左孩子丟 shan 了就完成了 很容易yy到的對吧 2.如何處理對當前數列中的數進行 k 開個全域性變數存整體的波動 值ff。那麼刪點的時候就把...

NOI2004 鬱悶的出納員

點此看題 這道題很新的一點就是加工資和減工資,這貌似要用到區間修改。但是細細想想,操作的物件是全樹,我們可以維護乙個累積的修改值,新加入乙個點的話要刪去之前的累計的修改值,對於減工資的情況,判斷有沒有低於最低的限制。注意如果乙個一來人就低於最低線,那麼這個人不被統計在最後的刪除人數中。include...