题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1208
题意: 中文题就不说了,都能看明白
解法: 数据结构题,应该使用一个BST类型的数据结构来实现,bst,treap,avl,splay,sbt,等等都可以。
我的解法是维护两个 spaly tree,A表示宠物,B表示收养者,
对于 a = 0, 添加宠物时, 首先检查 B是否为空, 若执行 A.insert( a ), 否则,调用方法 B.deal( a ).
deal( val ) 的思路: 若B中原本就有val值,则花费为0,直接删除key[x]=val的节点。 否则插入一个值为val的节点,
然后将其 splay( x, 0 ), 旋转到根, 然后找其 第一个比其小,与第一个比其大的,比较一下,小于或等于取左(题目要求),然后删除
选定的 l, 或者 r. 这时候还要删除多插入的 key[x] = val 的 x.
我是通过写了一个 remove( x ) 方法, 具体思路是,将其通过 splay( x, 0 ) 旋转到根,找其左或右第一个子节点 lch or rch, 则
lch or rch 存在则,必定 lch 无右孩子,rch 无左孩子,随便取一个替代x即可,处理下 指针关系即可。注意分情况考虑,因为lch or rch
可能不存在,此时需要分情况处理。
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int mod = (int)1e6; typedef long long LL; const int N = 80100; struct Splay{ int ch[N][2], pre[N], sz[N]; LL key[N]; int rt, top; void rotate(int x,int d){ int y = pre[x]; ch[y][d^1] = ch[x][d]; if( ch[x][d] ) pre[ch[x][d]] = y; if( pre[y] ) ch[pre[y]][ ch[pre[y]][1]==y ] = x; pre[x] = pre[y]; ch[x][d] = y; pre[y] = x; push_up(y); } void splay(int x,int goal){ while( pre[x] != goal ){ int y = pre[x]; if( pre[y] == goal ) rotate( x, ch[y][0]==x ); else{ int z = pre[y]; int d1 = ch[z][0]==y, d2 = ch[y][0]==x; if( d1 == d2 ) rotate(y,d1),rotate(x,d2); else rotate(x,d2), rotate(x,d1); } } if(goal == 0) rt = x; push_up(x); } void push_up(int x){ if( x ) sz[x] = 1+sz[ ch[x][0] ]+sz[ ch[x][1] ]; } void NewNode(int &x,LL c,int f){ x = ++top; ch[x][0]=ch[x][0]=0; pre[x]=f, key[x]=c, sz[x] = 1; } void init(){ ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; rt = top = 0; } void insert(int x, LL val, int f){ if( x == 0 ){ // if tree is empty NewNode(rt,val,0); return; } int d = val > key[x]; if( ch[x][d] != 0 ) insert( ch[x][d], val, x ); else{ NewNode( ch[x][d], val, x ); splay( ch[x][d], 0 ); } push_up(x); } int find(LL val){ int x = rt; while(x){ if( key[x] == val ) return x; x = ch[x][ val > key[x] ]; } return 0; } void remove(int x){ splay(x,0); if( ch[x][0] ){ int y = ch[x][0]; while( ch[y][1] ) y = ch[y][1]; splay( y, x ); ch[y][1] = ch[x][1]; pre[y] = pre[x]; if( ch[x][1] ) pre[ ch[x][1] ] = y; if( pre[x] ) ch[pre[x]][ch[pre[x]][1]==x] = y; if( x == rt ) rt = y; push_up(y); } else if( ch[x][1] ){ int y = ch[x][1]; while( ch[y][0] ) y = ch[y][0]; splay( y, x ); ch[y][0] = ch[x][0]; pre[y] = pre[x]; if( ch[x][0] ) pre[ ch[x][0] ] = y; if( pre[x] ) ch[pre[x]][ch[pre[x]][1]==x] = y; if( x == rt ) rt = y; push_up(y); } else rt = 0; } LL deal(LL val){ int x = find(val); LL sum; //printf("Find: x = %d\n", x ); if( x ){ remove(x); sum = 0; } else{ // printf("Deal pre:\n"); print(rt); insert( rt, val, 0 ); // printf("Deal:\n"); print(rt); x = find(val); splay(x,0); int l = ch[x][0], r = ch[x][1]; while( l && ch[l][1] ) l = ch[l][1]; while( r && ch[r][0] ) r = ch[r][0]; // printf("l = %d, r = %d\n", l, r ); if( l && r ){ if( (val-key[l]) <= (key[r]-val) ) sum = val-key[l], remove(l); else sum = key[r]-val, remove(r); } else if( l ){ sum = val-key[l], remove(l); } else if( r ){ sum = key[r]-val, remove(r); } remove(x); } return sum; } void print(int x){ if( x == 0 ){ printf("Empty!\n"); return; } if( ch[x][0] ) print( ch[x][0] ); printf("x=%d, lch=%d, rch=%d, pre=%d, sz=%d, key=%lld\n", x,ch[x][0],ch[x][1],pre[x],sz[x],key[x]); if( ch[x][1] ) print( ch[x][1] ); } }A, B; int main(){ int n; while( scanf("%d", &n) != EOF){ int a; LL b; LL res = 0; A.init(); B.init(); for(int i = 0; i < n; i++){ scanf("%d%lld", &a, &b); if( a == 0 ){ // dog if( B.sz[ B.rt ] == 0 ) A.insert(A.rt,b,0); else res += B.deal(b); /// printf("A:\n"); A.print( A.rt ); // printf("B:\n"); B.print( B.rt ); } else{ // people if( A.sz[ A.rt ] == 0 ) B.insert(B.rt,b,0); else res += A.deal(b); // printf("A:\n"); A.print( A.rt ); // printf("B:\n"); B.print( B.rt ); } res %= mod; } printf("%lld\n", res ); } return 0; }