[BZOJ3600]没有人的算术
生活随笔
收集整理的這篇文章主要介紹了
[BZOJ3600]没有人的算术
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
咕了這么久終于把這題補回來了...
關鍵在于怎么維護“數”的大小,直接用平衡樹即可,每個平衡樹節點維護的是一個實數區間$[l,r]$,那么$mid$就是這個節點所代表的“數”的大小,也即權值
如果我們使用的平衡樹在插入后需要調整樹的形態,那么被調整的部分的權值都需要被重新計算,如果平衡樹深度太大,那么精度會爆,所以要用重量平衡樹(修改影響到的子樹大小和平衡樹深度都不會太大)
這里用替罪羊樹,原生支持重新計算權值,過幾天補個旋轉treap咕咕咕
btw...替罪羊樹是不用記父親的...是我智障了
#include<stdio.h> typedef double du; const du al=.75; int max(int a,int b){return a>b?a:b;} du rk[500010]; struct num{int l,r;num(int a=0,int b=0){l=a;r=b;} }v[500010]; bool operator>(num a,num b){return rk[a.l]==rk[b.l]?rk[a.r]>rk[b.r]:rk[a.l]>rk[b.l];} bool operator==(num a,num b){return rk[a.l]==rk[b.l]&&rk[a.r]==rk[b.r];} int l[500010],r[500010],siz[500010],M,sc,rt,fs; du sl,sr; int insert(int&x,du lv,du rv,num d){du mv=(lv+rv)*.5;int t;if(x==0){x=++M;siz[x]=1;v[x]=d;rk[x]=mv;return x;}if(v[x]==d)return x;t=v[x]>d?insert(l[x],lv,mv,d):insert(r[x],mv,rv,d);siz[x]=siz[l[x]]+siz[r[x]]+1;if(sc&&(l[x]==sc||r[x]==sc))fs=x;if(siz[x]*al<max(siz[l[x]],siz[r[x]])){sc=x;sl=lv;sr=rv;}return t; } int tmp[500010],C; void dfs(int x){if(l[x])dfs(l[x]);tmp[++C]=x;if(r[x])dfs(r[x]); } int build(int L,int R,du lv,du rv){int mid=(L+R)>>1,x=tmp[mid];du mv=(lv+rv)*.5;rk[x]=mv;l[x]=L<mid?build(L,mid-1,lv,mv):0;r[x]=mid<R?build(mid+1,R,mv,rv):0;siz[x]=siz[l[x]]+siz[r[x]]+1;return x; } int insert(num d){sc=fs=0;int p=insert(rt,0,1,d);if(sc){C=0;dfs(sc);(sc!=rt?(l[fs]==sc?l:r)[fs]:rt)=build(1,C,sl,sr);}return p; } int mx[400010],pos[100010]; void modify(int p,int l,int r,int x){if(l==r){mx[x]=l;return;}int mid=(l+r)>>1;if(p<=mid)modify(p,l,mid,x<<1);elsemodify(p,mid+1,r,x<<1|1);l=mx[x<<1];r=mx[x<<1|1];mx[x]=rk[pos[l]]>=rk[pos[r]]?l:r; } int query(int L,int R,int l,int r,int x){if(L<=l&&r<=R)return mx[x];int mid=(l+r)>>1,res=0,t;if(L<=mid){t=query(L,R,l,mid,x<<1);if(rk[pos[t]]>rk[pos[res]])res=t;}if(mid<R){t=query(L,R,mid+1,r,x<<1|1);if(rk[pos[t]]>rk[pos[res]])res=t;}return res; } int main(){int n,m,i,l,r,k;char s[5];scanf("%d%d",&n,&m);rk[0]=-1;insert(num());for(i=1;i<=n;i++)pos[i]=1;for(i=1;i<=n;i++)modify(i,1,n,1);while(m--){scanf("%s%d%d",s,&l,&r);if(s[0]=='C'){scanf("%d",&k);pos[k]=insert(num(pos[l],pos[r]));modify(k,1,n,1);}elseprintf("%d\n",query(l,r,1,n,1));} }轉載于:https://www.cnblogs.com/jefflyy/p/9286077.html
總結
以上是生活随笔為你收集整理的[BZOJ3600]没有人的算术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IDEA自动编译less文件输出css
- 下一篇: 编程开发之--java多线程学习总结(5