【題解】Luogu P2073 送花
阿新 • • 發佈:2018-11-25
原題傳送門
這題需要用到Splay
我們用一棵splay維護金錢
考慮c<=1000000
我們珂以把每種價格現在對應的美麗值存在一個a陣列中
這樣講有珂能不太清楚qaq,還是對著操作一個一個講
操作一:
先在這棵splay中查詢是否有這種花的金錢
如果有,直接跳過
如果沒有,a[c]=m,把金錢為c的花的美麗值存下,把兩個所求答案更新,把c插入平衡樹
操作2,3:
執行所有操作之前先把inf,-inf插入平衡樹
刪除最小就是刪除-inf的後繼,刪除最大就是刪除inf的前驅
但還要加上特判,在後繼(前驅)不等於inf(-inf)的情況下,更新答案,a陣列變成0,把該節點從平衡樹中刪除
完整程式碼
#include <bits/stdc++.h> #define inf 1000000005 #define N 100005 #define root tree[0].ch[1] using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int read() { register int x=0,f=1;register char ch=nc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();} while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc(); return x*f; } inline void write(register int x) { if(!x)putchar('0');if(x<0)x=-x,putchar('-'); static int sta[20];register int tot=0; while(x)sta[tot++]=x%10,x/=10; while(tot)putchar(sta[--tot]+48); } struct Splay{ int v,fa,ch[2],sum; }tree[N]; int tot; inline bool findd(register int x) { return x==tree[tree[x].fa].ch[0]?0:1; } inline void connect(register int x,register int fa,register int son) { tree[x].fa=fa; tree[fa].ch[son]=x; } inline void update(register int x) { tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+1; } inline void rotate(register int x) { int Y=tree[x].fa; int R=tree[Y].fa; int Yson=findd(x); int Rson=findd(Y); int B=tree[x].ch[Yson^1]; connect(B,Y,Yson); connect(Y,x,Yson^1); connect(x,R,Rson); update(Y),update(x); } inline void splay(register int x,register int to) { to=tree[to].fa; while(tree[x].fa!=to) { int y=tree[x].fa; if(tree[y].fa==to) rotate(x); else if(findd(x)==findd(y)) rotate(y),rotate(x); else rotate(x),rotate(x); } } inline int newpoint(register int v,register int fa) { tree[++tot].fa=fa; tree[tot].v=v; tree[tot].sum=1; return tot; } inline void Insert(register int x) { int now=root; if(root==0) { newpoint(x,0); root=tot; } else { while(19260817) { ++tree[now].sum; int nxt=x<tree[now].v?0:1; if(!tree[now].ch[nxt]) { int p=newpoint(x,now); tree[now].ch[nxt]=p; splay(p,root); return; } now=tree[now].ch[nxt]; } } } inline int find(register int v) { int now=root; while(19260817) { if(tree[now].v==v) { splay(now,root); return now; } int nxt=v<tree[now].v?0:1; if(!tree[now].ch[nxt]) return 0; now=tree[now].ch[nxt]; } } inline void delet(register int x) { int pos=find(x); if(!pos) return; if(!tree[pos].ch[0]&&!tree[pos].ch[1]) root=0; else if(!tree[pos].ch[0]) { root=tree[pos].ch[1]; tree[root].fa=0; } else { int left=tree[pos].ch[0]; while(tree[left].ch[1]) left=tree[left].ch[1]; splay(left,tree[pos].ch[0]); connect(tree[pos].ch[1],left,1); connect(left,0,1); update(left); } } inline int lower(register int v) { int now=root; int ans=-inf; while(now) { if(tree[now].v<v&&tree[now].v>ans) ans=tree[now].v; if(v>tree[now].v) now=tree[now].ch[1]; else now=tree[now].ch[0]; } return ans; } inline int upper(register int v) { int now=root; int ans=inf; while(now) { if(tree[now].v>v&&tree[now].v<ans) ans=tree[now].v; if(v<tree[now].v) now=tree[now].ch[0]; else now=tree[now].ch[1]; } return ans; } int a[1000005]; int main() { Insert(inf); Insert(-inf); int opt=read(),ans1=0,ans2=0; while(opt!=-1) { if(opt==1) { int w=read(),c=read(); if(!find(c)) { ans1+=w,ans2+=c; a[c]=w; Insert(c); } } else if(opt==2) { int c=lower(inf); if(c!=-inf) { ans1-=a[c],ans2-=c; a[c]=0; delet(c); } } else { int c=upper(-inf); if(c!=inf) { ans1-=a[c],ans2-=c; a[c]=0; delet(c); } } opt=read(); } write(ans1),putchar(' '),write(ans2); return 0; }