国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

BZOJ 3196 Tyvj 1730 二逼平衡樹

2019-11-08 03:03:31
字體:
來源:轉載
供稿:網友

樹套樹裸題,練習模板的好去處。 注意每次SpLay修改前對原串的變動。

/**************************************************************    PRoblem: 3196    User: vermouth    Language: C++    Result: Accepted    Time:8124 ms    Memory:123440 kb****************************************************************/ #include<cstdio>#include<iostream>using namespace std;#define lson l,m,root<<1#define rson m+1,r,root<<1|1#define inf 0x3f3f3f3f const int maxn=250100; struct Splaytree{    int sz[maxn*20];    int ch[maxn*20][2];    int pre[maxn*20],rt[maxn<<2],top;    inline void up(int x)    {        sz[x] = sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];    }    inline void rotate(int x,int f)    {        int y=pre[x];        ch[y][!f]=ch[x][f];        pre[ch[x][f]]=y;        pre[x]=pre[y];        if(pre[x]) ch[pre[y]][ch[pre[y]][1]==y]=x;        ch[x][f]=y;        pre[y]=x;        up(y);    }    inline void Splay(int x,int goal,int root)    {        while(pre[x]!=goal)        {            if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);            else {                int y=pre[x],z=pre[y];                int f=(ch[z][0]==y);                if(ch[y][f]==x) rotate(x,!f),rotate(x,f);                else rotate(y,f),rotate(x,f);            }        }        up(x);        if(goal==0) rt[root]=x;    }    inline void RTO(int k,int goal,int root)    {        int x=rt[root];        while(sz[ch[x][0]]!=k-1)        {            if(k<sz[ch[x][0]]+1) x=ch[x][0];            else {                k-=(sz[ch[x][0]]+1);                x=ch[x][1];            }        }        Splay(x,goal,root);    }    inline void Newnode(int &x,int c)    {        x=++top;        ch[x][0]=ch[x][1]=pre[x]=0;        sz[x]=1;cnt[x]=1;        val[x]=c;    }    inline void init(){        top=0;    }    inline void Insert(int &x,int key,int f,int root){        if(!x){            Newnode(x,key);            pre[x]=f;            Splay(x,0,root);            return ;        }        if(key==val[x]){            cnt[x]++;            sz[x]++;            return ;        }else if(key<val[x]){            Insert(ch[x][0],key,x,root);        }else{            Insert(ch[x][1],key,x,root);        }        up(x);    }    void Del(int root){        if(cnt[rt[root]]>1){            cnt[rt[root]]--;        }        else        {            int t=rt[root];            if(ch[rt[root]][1]){                rt[root]=ch[rt[root]][1];                RTO(1,0,root);                ch[rt[root]][0]=ch[t][0];                if(ch[rt[root]][0]) pre[ch[rt[root]][0]]=rt[root];            }            else rt[root]=ch[rt[root]][0];            pre[rt[root]]=0;        }        up(rt[root]);    }    void findkey(int x,int key,int &ans)    {        if(!x) return ;        if(val[x]==key)             ans=x;        else if(val[x]>key)            findkey(ch[x][0],key,ans);        else            findkey(ch[x][1],key,ans);    }    inline int find_kth(int x,int k,int root){        if(k<sz[ch[x][0]]+1){            return find_kth(ch[x][0],k,root);        }else if(k>sz[ch[x][0]]+cnt[x])            return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x],root);        else {            Splay(x,0,root);            return val[x];        }    }    int findpre(int x,int z){        int ans=-inf;        while(ch[x][val[x]<=z])        {            if(val[x]<=z) ans=val[x];            x=ch[x][val[x]<=z];        }if(val[x]<=z) ans=max(ans,val[x]);        return ans;    }    int findsuc(int x,int z){        int ans=inf;        while(ch[x][val[x]<z])        {            if(val[x]>=z) ans=val[x];            x=ch[x][val[x]<z];        }if(val[x]>=z) ans=min(ans,val[x]);        return ans;    }    int val[maxn*20];    int cnt[maxn*20];    void build(int l,int r,int root)    {        rt[root]=0;        for(int i=l;i<=r;i++)            Insert(rt[root],a[i],0,root);        if(l>=r) return ;        int m=(l+r)>>1;        build(lson);        build(rson);    }    void update(int l,int r,int root,int i,int x)    {        int ans=0;        findkey(rt[root],a[i],ans);        Splay(ans,0,root);        Del(root);        Insert(rt[root],x,0,root);        if(l>=r) return ;        int m=(l+r)>>1;        if(i<=m) update(lson,i,x);        else update(rson,i,x);    }    int cntLess(int x,int key){        int ret=0;        while(x)        {            if(val[x]>key)                x=ch[x][0];            else            {                ret+=cnt[x]+sz[ch[x][0]];                x=ch[x][1];            }        }        return ret;    }    int getnumLess(int l,int r,int root,int L,int R,int x)    {        if(L<=l&&R>=r)        {            return cntLess(rt[root],x);        }        int m=(l+r)>>1;        int ret=0;        if(L<=m) ret+=getnumLess(lson,L,R,x);        if(R>m) ret+=getnumLess(rson,L,R,x);        return ret;    }    inline int get_pre(int l,int r,int root,int L,int R,int k)    {        if(L<=l&&R>=r)        {            return findpre(rt[root],k);        }        int ans=-inf;        int m=(l+r)>>1;        if(L<=m) ans=max(ans,get_pre(lson,L,R,k));        if(R>m) ans=max(ans,get_pre(rson,L,R,k));        return ans;    }    inline int get_suc(int l,int r,int root,int L,int R,int k)    {        if(L<=l&&R>=r)        {            return findsuc(rt[root],k);        }        int ans=inf;int m=(l+r)>>1;        if(L<=m) ans=min(ans,get_suc(lson,L,R,k));        if(R>m) ans=min(ans,get_suc(rson,L,R,k));        return ans;    }    int search(int L,int R,int k)    {        int l=0,r=inf;        int ans=0;        while(l<=r)        {            int m=(l+r)>>1;            int cnt=getnumLess(1,n,1,L,R,m);            if(cnt>=k)            {                r=m-1;ans=m;            }            else l=m+1;        }        return ans;    }    void solve()    {        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        build(1,n,1);        for(int i=1;i<=m;i++)        {            int x,y,z,op;            scanf("%d%d%d",&op,&x,&y);if(op!=3) scanf("%d",&z);            if(op==1) printf("%d/n",getnumLess(1,n,1,x,y,z-1)+1);            else if(op==2) printf("%d/n",search(x,y,z));            else if(op==3) update(1,n,1,x,y),a[x]=y;            else if(op==4) printf("%d/n",get_pre(1,n,1,x,y,z-1));            else if(op==5) printf("%d/n",get_suc(1,n,1,x,y,z+1));         }    }    int a[maxn];    int n,m;} spt;int T; int main(){    spt.init();    spt.solve();    return 0;}/*30 10347297 7767863 4687361 4266761 1869189 6183125 6228737 7377798 2298221 253439 2279737 7603021 9596641 3461977 8857135 7648897 1264321 7381859 2257573 3750694 7066537 7631697 3115165 3367245 3742733 7943233 4901377 2381377 3162917 3567345 1 7 26 22982213 19 6712240 4 23 29 37431065 7 24 76247121 7 22 70665375 1 18 2518942 19 21 15 15 16 88557742 1 12 103 15 3539397 */
上一篇:排序--歸并排序

下一篇:空格替換練習

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 伽师县| 海伦市| 炎陵县| 盖州市| 东至县| 乌兰县| 志丹县| 广河县| 宁强县| 西藏| 蒲城县| 松阳县| 玛曲县| 四子王旗| 石林| 滨海县| 湾仔区| 子洲县| 济南市| 寻乌县| 丰城市| 朝阳区| 牡丹江市| 方山县| 安图县| 南华县| 精河县| 务川| 班玛县| 儋州市| 永嘉县| 永寿县| 科尔| 防城港市| 曲阳县| 上林县| 毕节市| 郴州市| 青神县| 江孜县| 玉环县|