• (WA)BZOJ 1503: [NOI2004]郁闷的出纳员


    二次联通门 : BZOJ 1503: [NOI2004]郁闷的出纳员

    /*
        BZOJ 1503: [NOI2004]郁闷的出纳员
        
        考虑这样一个事实
        无论是加或减
        都是针对全体人员的
        
        那么只需要记录一个总标记
        
        直接记录对于工资的加或减
        
        每次查询最低要求工资与标记的差的前驱,并旋到根处 
        
        那么根节点的所有左子树都是不符合要求要走人的
        每次记录一下搞一搞, 就不用考虑splay麻烦的标记下放问题了 
        
      但是却没调出来。。。
    */ #include <cstdio> void read (int &now) { register char word = getchar (); bool temp = false; for (now = 0; word < '0' || word > '9'; word = getchar ()) if (word == '-') temp = true; for (; word >= '0' && word <= '9'; now = now * 10 + word - '0', word = getchar ()); if (temp) now = -now; } int Min_N; struct S_D { S_D *child[2], *father; int key; int weigth, size; inline void Updata () { this->size = this->weigth; if (this->child[0]) this->size += this->child[0]->size; if (this->child[1]) this->size += this->child[1]->size; } S_D () { child[0] = child[1] = NULL; size = weigth = 1; key = 0; father = NULL; } inline int Get_Pos () { return this->father->child[1] == this; } inline void Clear () { this->child[0] = this->child[1] = father = NULL; } }; int Answer; class Splay_Tree_Type { private : S_D *Root; inline void Rotate (S_D *now) { S_D *Father = now->father; register int pos = now->Get_Pos () ^ 1; Father->child[pos ^ 1] = now->child[pos]; if (now->child[pos]) now->child[pos]->father = Father; if ((now->father = Father->father) != NULL) now->father->child[now->father->child[1] == Father] = now; Father->father = now; now->child[pos] = Father; Father->Updata (); now->Updata (); if (now->father == NULL) Root = now; } inline void Splay (S_D *now) { for (S_D *Father; Father = now->father; this->Rotate (now)) if (Father->father != NULL) this->Rotate (now->Get_Pos () == Father->Get_Pos () ? Father : now); } S_D* Find (int x) { S_D *now = Root; for (; (now != NULL && now->key != x); now = now->child[x > now->key]); if (now == NULL) return now; Splay (now); return now; } void Delete_point (int x) { S_D *now = Find (x); if (now->weigth > 1) { now->weigth --; return ; } if (now->child[0] == NULL && now->child[1] == NULL) { now->Clear (); Root = NULL; return ; } S_D *res; if (now->child[0] == NULL) { Root = now->child[1]; now->child[1]->father = NULL; now->Clear (); return ; } if (now->child[1] == NULL) { Root = now->child[0]; now->child[0]->father = NULL; now->Clear (); return ; } S_D *Prefix = Find_Prefix (x); res = Root; Prefix->child[1] = res->child[1]; res->child[1]->father = Root; res->Clear (); Root->Updata (); } void Delete_tree (int x) { S_D *now = Find_Suffix (x); if (now == NULL) return ; Answer += now->child[0]->size; now->child[0]->father = NULL; now->child[0] = NULL; now->Updata (); } S_D *Find_Suffix (int x) { this->Insert (x); S_D *now = Root; if (now->child[1] == NULL) { this->Delete_point (x); return NULL; } for (now = now->child[1]; now->child[0]; now = now->child[0]); this->Delete_point (x); if (now == NULL) return now; this->Splay (now); return now; } S_D *Find_Prefix (int x) { this->Insert (x); S_D *now = Root; if (now->child[0] == NULL) { this->Delete_point (x); return NULL; } for (now = now->child[0]; now->child[1]; now = now->child[1]); this->Delete_point (x); if (now == NULL) return now; this->Splay (now); return now; } public : int Flandre_Scarlet; void Insert (int x) { if (Root == NULL) { Root = new S_D ; Root->key = x; return ; } S_D *now = Root, *Father; for (; ;Father = now, now = now->child[x > now->key]) { if (now == NULL) { now = new S_D; now->key = x; now->father = Father; Father->child[x > Father->key] = now; this->Splay (now); return ; } if (x == now->key) { now->weigth ++; this->Splay (now); return ; } } } void Cut (int x) { int Need = Min_N - Flandre_Scarlet; S_D *now = this->Find_Prefix (Need); if (now != NULL) this->Delete_tree (now->key); } int Query (int x) { S_D *now = Root; for (register int res = 0; ; ) { if (now->child[0] && x < now->child[0]->size) now = now->child[0]; res += (now->child[0] ? now->child[0]->size : 0) + now->weigth; if (x <= res) return now->key; x -= res; now = now->child[1]; } } void Change (int x) { Flandre_Scarlet += x; return ; } int Query_Size () { return Root->size; } }; Splay_Tree_Type Splay; int main (int argc, char *argv[]) { freopen ("cashier.in", "r", stdin); freopen ("cashier.out", "w", stdout); int N; read (N); read (Min_N); char type[3]; register int Size; for (int x; N --; ) { scanf ("%s", type); read (x); if (type[0] == 'I') Splay.Insert (x); else if (type[0] == 'S') Splay.Change (-x); else if (type[0] == 'A') Splay.Change (x); else { Splay.Cut (x); Size = Splay.Query_Size (); if (x > Size) puts ("-1"); else printf ("%d ", Splay.Query (Size - x) + Splay.Flandre_Scarlet); } } printf ("%d", Answer); return 0; } /* 20 0 I 4 F 1 I 6 S 9 F 14 I 6 I 7 A 8 I 3 F 2 I 9 I 6 I 6 S 3 S 5 I 6 F 1 I 3 A 2 F 5 */ /* 4 -1 14 7 3 5 */
  • 相关阅读:
    解决:std::ostream operator<< should have been declared inside 'xxx'
    c++ friend 遇到 namespace 无法访问 private 成员的问题
    Compiler Error C2872: ambiguous symbol
    【持续更新】总结:C++开发时积累的一些零碎的东西
    陷阱:C++模块之间的”直接依赖“和”间接依赖“与Makefile的撰写
    ZThread::ThreadLocal:ERROR C4716 must return a value的解决
    java值传递
    iframe与父页面传值
    iframe父子兄弟之间调用传值(contentWindow && parent)
    MySQL返回影响行数的测试示例
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7191565.html
Copyright © 2020-2023  润新知