題目:鬱悶的出納員
做法:了解平衡樹這個資料結構的人應該一眼就能看出這個題目可以用平衡樹做(平衡樹的教程網上太多了,這裡就不贅述了),用平衡樹維護插入、刪除、查詢第k小(注意由於題目中詢問第k大,就是查詢第(目前員工數-k+1)小)的操作即可,再用乙個數delta來記錄工資的整體變化量,注意處理就可以了。
以下是本人**:
treap 樹堆(2016.8.10):
#include #include #include #include #include using namespace std;
int m,n,k,delta=0,root=0,cnt=0,ans=0;
char op;
struct node
}tree[100010];
void rotate(int &v,bool p)
void insert(int &v,int key)
else
int main()
if (op=='a') delta+=k;
if (op=='s')
if (op=='f')
}printf("%d\n",ans);
return 0;
}
splay tree 伸展樹(2016.8.26):
#include #include #include #include #include using namespace std;
int n,m,root=0,top=0,delta=0,ans=0;
int ch[100010][2],pre[100010],siz[100010],val[100010],c[100010],k;
char op[20];
void up(int x)
void rotate(int x,int f)
void splay(int x,int goal)
} up(x);
if (goal==0) root=x;
}void newnode(int &v,int key,int f)
void insert(int &v,int key,int f)
if (key==val[v])
insert(ch[v][key>val[v]],key,v);
up(v);
}int get_kth(int x,int k)
}int getkey(int x,int key)
}void rto(int k,int goal)
else break;
} splay(x,goal);
}void del_root()
else root=ch[root][0];
pre[root]=0;
up(root);
}void delete(int key)
int main()
if (op[0]=='a') delta+=k;
if (op[0]=='s')
{ delta-=k;
int min;
while(siz[root]&&(min=get_kth(root,1))
noi 2004 鬱悶的出納員
原題位址 花了一兩天真正的熟悉了treap,對於乙個東西,本蒟蒻認為,不應該要會,還應會熟練的寫,像哈狗寫這個只需十分鐘 好吧,話歸正題 先推薦另類解法 戳進去 此題解法很多bit 權值線段樹 各種平衡樹 準備抽空寫 是一道很棒的模板題。這道題我們把每次全體加的工資和減的弄到乙個變數,姑且叫為w,把...
NOI2004 鬱悶的出納員
大致題意就是對初始為空的數列的各種操作233 題解 splay啦 其中可能會遇到的幾個問題 1.如何刪去低於min的點 找到數列中min的後繼提為根,把根的左孩子丟 shan 了就完成了 很容易yy到的對吧 2.如何處理對當前數列中的數進行 k 開個全域性變數存整體的波動 值ff。那麼刪點的時候就把...
NOI2004 鬱悶的出納員
點此看題 這道題很新的一點就是加工資和減工資,這貌似要用到區間修改。但是細細想想,操作的物件是全樹,我們可以維護乙個累積的修改值,新加入乙個點的話要刪去之前的累計的修改值,對於減工資的情況,判斷有沒有低於最低的限制。注意如果乙個一來人就低於最低線,那麼這個人不被統計在最後的刪除人數中。include...