[NOI2004]郁悶的出納員
阿新 • • 發佈:2018-12-02
tps har mat iostream 開始 ems clu write name ,查詢的時候應該查第\(k + 1\)大的元素。
然後因為我剛開始學,所以因為各種小毛病調了好久……
嘟嘟嘟
\(splay\)我又來了
1.插入結點:正常操作,不說了。
1.全局加減:單開一個變量表示變化量即可,不用區間修改打\(lazy\)標記。
2.刪除小於\(x\)的數:找\(x\)的後繼(包括自己),然後把\(x\)旋到根,刪除左子樹即可。
3.查詢第\(k\)大的數:如果\(k\)小於右子樹大小,到右子樹去找;否則如果\(k\)小於右子樹大小加上當前節點大小\(size\),直接返回當前節點權值;否則\(k -= size\),去左子樹找。
主要思路就是這些。
細節:
1.別忘了先往樹裏添加\(-INF\)和\(INF\),防止出現找不到前驅或者後繼的情況。
2.由於第一條,所以每次刪除後要再添加\(-INF\)
然後因為我剛開始學,所以因為各種小毛病調了好久……
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(‘ ‘) #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 1e6 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ‘ ‘; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - ‘0‘, ch = getchar(); if(last == ‘-‘) ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar(‘-‘); if(x >= 10) write(x / 10); putchar(x % 10 + ‘0‘); } int n, Min, delta = 0, sum = 0; char c[2]; struct Tree { int ch[2], fa; int siz, cnt, val; }t[maxn]; int root, ncnt = 0; void _PrintTree(int now) //調試用 { if(!now) return; printf("nd:%d val:%d lsval:%d rsval:%d\n", now, t[now].val, t[t[now].ch[0]].val, t[t[now].ch[1]].val); _PrintTree(t[now].ch[0]); _PrintTree(t[now].ch[1]); } void _SizCk(int now) { if(!now) return; if(t[now].siz != t[t[now].ch[0]].siz + t[t[now].ch[1]].siz + t[now].cnt) printf("Size Error! %d\n",now); _SizCk(t[now].ch[0]); _SizCk(t[now].ch[1]); } void pushup(int now) { t[now].siz = t[t[now].ch[0]].siz + t[t[now].ch[1]].siz + t[now].cnt; } void rotate(int x) { int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x); t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z; t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].fa = y; t[x].ch[k ^ 1] = y; t[y].fa = x; pushup(y); pushup(x); //first x,after y //_SizCk(x); } void splay(int x, int s) { while(t[x].fa != s) { int y = t[x].fa, z = t[y].fa; if(z != s) { if((x == t[y].ch[1]) ^ (y == t[z].ch[1])) rotate(x); else rotate(y); } rotate(x); } if(!s) root = x; } void insert(int x) int now = root, f = 0; while(now && t[now].val != x) f = now, now = t[now].ch[x > t[now].val]; if(now) t[now].cnt++; else { now = ++ncnt; if(f) t[f].ch[x > t[f].val] = now; t[now].fa = f; t[now].ch[0] = t[now].ch[1] = 0; t[now].siz = t[now].cnt = 1; t[now].val = x; } splay(now, 0); } void find(int x) { int now = root; while(t[now].val != x && t[now].ch[x > t[now].val]) now = t[now].ch[x > t[now].val]; splay(now, 0); //_PrintTree(root); } int nxt(int x) { find(x); if(t[root].val >= x) return root; int now = t[root].ch[1]; while(t[now].ch[0]) now = t[now].ch[0]; return now; } void clear(int& now) { t[now].val = t[now].siz = t[now].cnt = 0; t[now].fa = t[now].ch[0] = t[now].ch[1] = 0; now = 0; } int del(int x) //nxt(x) go to root, and del left son //the num >= x! { int now = nxt(x); splay(now, 0); int ret = t[t[root].ch[0]].siz; clear(t[root].ch[0]); pushup(root); return ret; } int query(int k) { int now = root; while(1) { if(k <= t[t[now].ch[1]].siz) now = t[now].ch[1]; else if(k <= t[t[now].ch[1]].siz + t[now].cnt) return t[now].val; else k -= t[t[now].ch[1]].siz + t[now].cnt, now = t[now].ch[0]; } } int main() { insert(-INF); insert(INF); n = read(); Min = read(); for(int i = 1; i <= n; ++i) { scanf("%s", c); int x = read(); if(c[0] == ‘I‘ && x >= Min) insert(x - delta); else if(c[0] == ‘A‘) delta += x; else if(c[0] == ‘S‘) delta -= x, sum += del(Min - delta) - 1, insert(-INF); else if(c[0] == ‘F‘) { x++; //有INF if(t[root].siz < x + 1) write(-1), enter; else write(query(x) + delta), enter; } //_PrintTree(root); } write(sum), enter; return 0; }
[NOI2004]郁悶的出納員