【替罪羊樹-動態標號+線段樹】BZOJ3600[沒有人的算術]題解

題目概述

定義一種數,這種數只有 0(a,b) ,其中 a,b 是這種數。

定義 < :1. 0 最小。2. (a,b)<(c,d),c>a 。3. (a,b)<(a,c),c>b

現在有 n 個這種數,剛開始都是 0 。給出 m 個操作:1.將 a[k] 賦值爲 (a[l],a[r]) 。2.詢問 [l,r] 中最大值的編號,有多個最大值取最小編號。

解題報告

詢問是裸的線段樹,但是真的按題目意思去比大小的話就會非常複雜,實際上我們可以按照這種數的大小關係將每個數都等價爲一個實數,然後我們比較實數大小就行了。

因爲每次會產生新的數,所以這是一個動態標號問題。快速確定位置可以用平衡樹,但是Treap,Splay等旋轉平衡樹顯然無法快速編號。這樣的話我們可以用替罪羊樹或者非旋Treap。因爲替罪羊樹好打就用替罪羊樹好了~

解題報告

第一次用Emacs打代碼,真的是心累QAQ。

#include<cstdio>
#include<cctype>
#include<algorithm>
#define fr first
#define sc second
#define mp make_pair
using namespace std;
typedef long double DB;
const int maxn=1e5,maxt=6e5;const DB AL=0.75;

int n,te,Tail,MAX[(maxn<<2)+5];
struct node{
    node *son[2];pair<node*,node*> val;DB now;int si;node() {}
    node(node *p,pair<node*,node*> v,DB k=0,int s=1) {son[0]=son[1]=p;val=v;now=k;si=s;}
    inline void Pushup() {si=son[0]->si+1+son[1]->si;}
    inline bool isbad() {return si*AL<max(son[0]->si,son[1]->si);}
}nil(&nil,mp(&nil,&nil),0,0);
typedef node* P_node;typedef pair<P_node,P_node> data;
bool operator < (const data &a,const data &b) {return a.fr->now<b.fr->now||a.fr->now==b.fr->now&&a.sc->now<b.sc->now;}
bool operator == (const data &a,const data &b) {return a.fr==b.fr&&a.sc==b.sc;}
node tem[maxt+5];P_node si=tem,null=&nil,ro=null;
DB sl,sr;P_node ID[maxn+5],que[maxt+5],*sgt;

#define Eoln(x) ((x)==10||(x)==13||(x)==EOF)
inline char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF;return *l++;
}
inline int readi(int &x){
    int tot=0,f=1;char ch=readc(),lst='+';
    while (!isdigit(ch)) {if (ch==EOF) return EOF;lst=ch;ch=readc();}
    if (lst=='-') f=-f;
    while (isdigit(ch)) tot=(tot<<3)+(tot<<1)+ch-48,ch=readc();
    return x=tot*f,Eoln(ch);
}
inline char getfst() {char ch=readc();while (ch!='C'&&ch!='Q') ch=readc();return ch;}
#define newnode(v,k) (*si=node(null,v,k),si++)
P_node ins(P_node &p,data k,DB l=0,DB r=1){
    DB m=(l+r)/2;if (p==null) p=newnode(k,m);if (k==p->val) return p;P_node now;
    if (k<p->val) now=ins(p->son[0],k,l,m); else now=ins(p->son[1],k,m,r);
    p->Pushup();if (p->isbad()) sgt=&p,sl=l,sr=r;return now;
}
void Dfs(P_node p){
    if (p==null) return;
    Dfs(p->son[0]);que[++Tail]=p;Dfs(p->son[1]);
}
P_node Build(int L,int R,DB l,DB r){
    if (L>R) return null;int mid=L+(R-L>>1);DB m=(l+r)/2;que[mid]->now=m;
    que[mid]->son[0]=Build(L,mid-1,l,m);que[mid]->son[1]=Build(mid+1,R,m,r);
    que[mid]->Pushup();return que[mid];
}
#define Rebuild Tail=0,Dfs(*sgt),*sgt=Build(1,Tail,sl,sr)
inline P_node Insert(data k) {sgt=0;P_node now=ins(ro,k);if (sgt) Rebuild;return now;}
#define LS (p<<1)
#define RS (p<<1|1)
#define Fix(x,y) if (ID[y]->now>ID[x]->now||ID[y]->now==ID[x]->now&&y<x) x=y
inline void Pushup(int p) {MAX[p]=MAX[LS];Fix(MAX[p],MAX[RS]);}
void Update(int pos,int l=1,int r=n,int p=1){
    if (pos<l||r<pos) return;if (l==r) {MAX[p]=pos;return;}
    int mid=l+(r-l>>1);Update(pos,l,mid,LS);Update(pos,mid+1,r,RS);Pushup(p);
}
inline int Maxer(int x,int y) {Fix(x,y);return x;}
int Ask(int L,int R,int l=1,int r=n,int p=1){
    if (R<l||r<L) return 0;if (L<=l&&r<=R) return MAX[p];
    int mid=l+(r-l>>1);return Maxer(Ask(L,R,l,mid,LS),Ask(L,R,mid+1,r,RS));
}
int main(){
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);
    readi(n);ID[0]=null;for (int i=1;i<=n;i++) ID[i]=Insert(mp(null,null)),Update(i);
    for (readi(te);te;te--){
        char td=getfst();int L,R,k;readi(L);readi(R);
        if (td=='C') readi(k),ID[k]=Insert(mp(ID[L],ID[R])),Update(k); else
        printf("%d\n",Ask(L,R));
    }
    return 0;
}
發佈了340 篇原創文章 · 獲贊 124 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章