[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维护顾客和宠物;
当然也可以用两棵树分别维护;
重点就是寻找前驱和后继;
#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; }