[HNOI2004]宠物收养场 BZOJ1208 splay tree
题目描述
凡凡开了一间宠物收养场。收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。
每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养场的宠物一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养场总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少。
被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为a,那么它将会领养一只目前未被领养的宠物中特点值最接近a的一只宠物。(任何两只宠物的特点值都不可能是相同的,任何两个领养者的希望领养宠物的特点值也不可能是一样的)如果有两只满足要求的宠物,即存在两只宠物他们的特点值分别为a-b和a+b,那么领养者将会领养特点值为a-b的那只宠物。
收养宠物的人过多,假若到来一只被收养的宠物,那么哪个领养者能够领养它呢?能够领养它的领养者,是那个希望被领养宠物的特点值最接近该宠物特点值的领养者,如果该宠物的特点值为a,存在两个领养者他们希望领养宠物的特点值分别为a-b和a+b,那么特点值为a-b的那个领养者将成功领养该宠物。
一个领养者领养了一个特点值为a的宠物,而它本身希望领养的宠物的特点值为b,那么这个领养者的不满意程度为abs(a-b)。
你得到了一年当中,领养者和被收养宠物到来收养所的情况,请你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。
输入输出格式
输入格式:第一行为一个正整数n,n<=80000,表示一年当中来到收养场的宠物和领养者的总数。接下来的n行,按到来时间的先后顺序描述了一年当中来到收养场的宠物和领养者的情况。每行有两个正整数a, b,其中a=0表示宠物,a=1表示领养者,b表示宠物的特点值或是领养者希望领养宠物的特点值。(同一时间呆在收养所中的,要么全是宠物,要么全是领养者,这些宠物和领养者的个数不会超过10000个)
输出格式:仅有一个正整数,表示一年当中所有收养了宠物的领养者的不满意程度的总和mod 1000000以后的结果。
输入输出样例
5 0 2 0 4 1 3 1 2 1 5
3 注:abs(3-2) + abs(2-4)=3, 最后一个领养者没有宠物可以领养。
用一颗splay tree维护顾客和宠物;
当然也可以用两棵树分别维护;
重点就是寻找前驱和后继;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | #include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> #include<ctime> #include<deque> #include<stack> #include<functional> #include<sstream> //#include<cctype> //#pragma GCC optimize(2) using namespace std; #define maxn 200005 #define inf 0x3f3f3f3f //#define INF 1e18 #define rdint(x) scanf("%d",&x) #define rdllt(x) scanf("%lld",&x) #define rdult(x) scanf("%lu",&x) #define rdlf(x) scanf("%lf",&x) #define rdstr(x) scanf("%s",x) typedef long long ll; typedef unsigned long long ull; typedef unsigned int U; #define ms(x) memset((x),0,sizeof(x)) const long long int mod = 1e9 + 7; #define Mod 1000000000 #define sq(x) (x)*(x) #define eps 1e-3 typedef pair< int , int > pii; #define pi acos(-1.0) const int N = 1005; #define REP(i,n) for(int i=0;i<(n);i++) typedef pair< int , int > pii; inline ll rd() { ll x = 0; char c = getchar (); bool f = false ; while (! isdigit (c)) { if (c == '-' ) f = true ; c = getchar (); } while ( isdigit (c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar (); } return f ? -x : x; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } ll sqr(ll x) { return x * x; } /*ll ans; ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1; y = 0; return a; } ans = exgcd(b, a%b, x, y); ll t = x; x = y; y = t - a / b * y; return ans; } */ int n; struct node { int ch[2]; int val; int ff; }t[maxn<<1]; int rt; int tot; void rotate( int x) { int y = t[x].ff; int z = t[y].ff; int k = (x == t[y].ch[1]); t[z].ch[y == t[z].ch[1]] = x; t[x].ff = z; t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].ff = y; t[x].ch[k ^ 1] = y; t[y].ff = x; } void splay( int x, int aim) { while (t[x].ff != aim) { int y = t[x].ff; int z = t[y].ff; if (z != aim) { (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y); } rotate(x); } if (aim == 0)rt = x; } void Insert( int x) { int now = rt, ff = 0; while (now&&t[now].val != x) { ff = now; now = t[now].ch[t[now].val < x]; } if (now); else { now = ++tot; if (ff)t[ff].ch[t[ff].val < x] = now; t[now].ff = ff; t[now].ch[0] = t[now].ch[1] = 0; t[now].val = x; } splay(now, 0); } void Find( int x) { int now = rt; if (now == 0) return ; while (t[now].ch[x > t[now].val] && x != t[now].val) { now = t[now].ch[x > t[now].val]; } splay(now, 0); } int nxt1( int x, int f) { Find(x); int now = rt; if (t[now].val >= x && f) return now; if (t[now].val <= x && !f) return now; now = t[now].ch[f]; while (t[now].ch[f ^ 1])now = t[now].ch[f ^ 1]; return now; } int nxt2( int x, int f) { Find(x); int now = rt; if (t[now].val > x&&f) return now; if (t[now].val < x && !f) return now; now = t[now].ch[f]; while (t[now].ch[f ^ 1])now = t[now].ch[f ^ 1]; return now; } void del( int x) { int l = nxt2(x, 0); int r = nxt2(x, 1); splay(l, 0); splay(r, l); // split操作 t[r].ch[0] = 0; } int main() { //ios::sync_with_stdio(0); rdint(n); int cnt = 0, ans = 0; Insert(inf); Insert(-inf); REP(i, n) { int op, x; rdint(op); rdint(x); if (cnt == 0)Insert(x); if (cnt > 0) { // 宠物splay树 if (op == 0)Insert(x); else { int tmp1 = t[nxt1(x, 0)].val; //前驱 int tmp2 = t[nxt1(x, 1)].val; // 后继 if ( abs (tmp1 - x) <= abs (tmp2 - x)) { (ans += abs (tmp1 - x)) %= 1000000; del(tmp1); //删除节点 } else { (ans += abs (tmp2 - x)) %= 1000000; del(tmp2); } } } if (cnt < 0) { // 顾客splay树 if (op == 1)Insert(x); else { int tmp1 = t[nxt1(x, 0)].val; int tmp2 = t[nxt1(x, 1)].val; if ( abs (tmp1 - x) <= abs (tmp2 - x)) { (ans += ( abs (tmp1 - x))) %= 1000000; del(tmp1); } else { (ans += ( abs (tmp2 - x))) %= 1000000; del(tmp2); } } } cnt = cnt + (op == 0 ? 1 : -1); } cout << ans << endl; return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义