【BZOJ3600】沒有人的算術 - 替罪羊樹+線段樹

題意:

 

題解:

Orz vfleaking……真·神題node

作法大概是先把題意中定義的「數」都賦一個實數權值,用平衡樹來維護整個從大到小排序過的序列,再用線段樹查詢最值;ios

這樣作爲何是對的?考慮插入一個數$x$,咱們已經知道了$x_L$和$x_R$在序列中的位置,就能夠直接每次$O(1)$比較權值大小來找到$x$應該插入的位置,這樣子單次插入是$O(logn)$的;git

再考慮賦值,能夠把根節點的區間設爲$(0,1)$,而後每一個點的權值都賦爲這個區間中點的值,向子樹遞歸賦值便可;因爲平衡樹樹高是$O(logn)$的,最小精度限制就是$2^{-logn}=\frac{1}{n}$的,能夠直接用double存;可是一個問題是普通的平衡樹在旋轉以後整棵子樹的權值都須要從新計算,所以就要用不須要旋轉的重量平衡樹,這裏我用的替罪羊樹;ui

ps:貌似我寫的替罪羊是假的……rebuild的地方會重複rec不少次……alpha小了會T,大了會WA……通過面對oj調參+玄學讀優才卡時限過……spa

代碼:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 1000000007
 8 #define eps 1e-9
 9 using namespace std;  10 typedef long long ll;  11 typedef double db;  12 const db alpha=0.865;  13 int n,m,l,r,k,rt=0,cur,cnt=0,top=0,nw[500001],st[500001];  14 db s[500001];  15 char op[3];  16 struct num{  17     int x,y;  18  num(){}  19     num(int _x,int _y){  20         x=_x,y=_y;  21  }  22     friend bool operator ==(num a,num b){  23         return a.x==b.x&&a.y==b.y;  24  }  25     friend bool operator <(num a,num b){  26         return a.x==b.x?s[a.y]<s[b.y]:s[a.x]<s[b.x];  27  }  28 };  29 struct node{  30     int ls,rs,siz;  31     //db s;
 32  num v;  33 }t[500001];  34 struct _node{  35     int v,p;  36 }tr[500001];  37 char buffer[6000010],*hd,*tl;  38 inline char Getchar(){  39     if(hd==tl){  40         int len=fread(buffer,1,6000009,stdin);  41         hd=buffer,tl=hd+len;  42         if(hd==tl)  43             return EOF;  44  }  45     return *hd++;  46 }  47 inline int rd(){  48     register int x=0,f=1;  49     char c;  50     do{  51         c=Getchar();  52         if(c=='-')f=-1;  53     }while(!isdigit(c));  54     do{  55         x=(x<<1)+(x<<3)+(c^48);  56         c=Getchar();  57     }while(isdigit(c));  58     return x*f;  59 }  60 void getmx(num &a,num b){  61     if((a.y==b.y&&a.x>b.x)||s[a.y]<s[b.y])a=b;  62 }  63 bool ndrb(int u){  64     return t[t[u].ls].siz>t[u].siz*alpha+5||t[t[u].rs].siz>t[u].siz*alpha+5;  65 }  66 void rec(int u){  67     if(t[u].ls)rec(t[u].ls);  68     st[++top]=u;  69     if(t[u].rs)rec(t[u].rs);  70 }  71 void rebuild(int &u,int l,int r,db L,db R){  72     int mid=(l+r)/2;  73     db Mid=(L+R)/2;  74     u=st[mid];  75     s[u]=Mid;  76     t[u].ls=t[u].rs=0;  77     if(l<mid)rebuild(t[u].ls,l,mid-1,L,Mid);  78     if(mid<r)rebuild(t[u].rs,mid+1,r,Mid,R);  79     t[u].siz=t[t[u].ls].siz+t[t[u].rs].siz;  80 }  81 void rb(int &u,db L,db R){  82     top=0;  83  rec(u);  84     rebuild(u,1,top,L,R);  85 }  86 int ins(int &u,db L,db R,num x){  87     db Mid=(L+R)/2;  88     if(!u){  89         u=++cnt;  90         t[u].v=x;  91         s[u]=Mid;  92         t[u].ls=t[u].rs=0;  93         t[u].siz=1;  94         return u;  95  }  96     t[u].siz++;  97     if(ndrb(u))rb(u,L,R);  98     if(x==t[u].v)return u;  99     else if(x<t[u].v)return ins(t[u].ls,L,Mid,x); 100     else return ins(t[u].rs,Mid,R,x); 101 } 102 void pushup(int u){ 103     if(tr[u*2].v==tr[u*2+1].v||s[tr[u*2].v]>s[tr[u*2+1].v]){ 104         tr[u].v=tr[u*2].v; 105         tr[u].p=tr[u*2].p; 106     }else{ 107         tr[u].v=tr[u*2+1].v; 108         tr[u].p=tr[u*2+1].p; 109  } 110 } 111 void build(int l,int r,int u){ 112     tr[u].v=1; 113     tr[u].p=l; 114     if(l==r)return; 115     int mid=(l+r)/2; 116     build(l,mid,u*2); 117     build(mid+1,r,u*2+1); 118 } 119 void updata(int l,int r,int u,int p){ 120     if(l==r){ 121         tr[u].v=nw[l]; 122         tr[u].p=l; 123         return; 124  } 125     int mid=(l+r)/2; 126     if(p<=mid)updata(l,mid,u*2,p); 127     else updata(mid+1,r,u*2+1,p); 128  pushup(u); 129 } 130 num query(int l,int r,int u,int L,int R){ 131     if(L<=l&&r<=R){ 132         return num(tr[u].p,tr[u].v); 133  } 134     int mid=(l+r)/2; 135     num ret(0,0); 136     if(L<=mid)getmx(ret,query(l,mid,u*2,L,R)); 137     if(mid<R)getmx(ret,query(mid+1,r,u*2+1,L,R)); 138     return ret; 139 } 140 int main(){ 141  #ifndef ONLINE_JUDGE 142     freopen("10.in","r",stdin); 143     freopen("my.out","w",stdout); 144     #endif 
145     //scanf("%d%d",&n,&m);
146     n=rd(),m=rd(); 147     cur=ins(rt,0,1,num(1,0)); 148     for(int i=1;i<=n;i++)nw[i]=cur; 149     build(1,n,1); 150     for(int i=1;i<=m;i++){ 151         //scanf("%s%d%d",op,&l,&r);
152         char ch; 153         ch=Getchar(); 154         while(ch!='C'&&ch!='Q')ch=Getchar(); 155         l=rd(),r=rd(); 156         if(ch=='C'){ 157             //scanf("%d",&k);
158             k=rd(); 159             nw[k]=ins(rt,0,1,num(nw[l],nw[r])); 160             updata(1,n,1,k); 161         }else printf("%d\n",query(1,n,1,l,r).x); 162  } 163     return 0; 164 }
相關文章
相關標籤/搜索