码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1552

时间:2017-05-28 20:49:51      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:nod   str   bzoj   open   getchar   ==   离散化   name   hid   

这道题用splay写 先离散化数据保证按题目所述顺序来写 按原序作为键值建树 维护区间最小值去跑 每次将i的位置 和 n的位置x和y找出来后 将x旋转到root y旋转到x的有儿子 这时y的左子树就是所求区间 找出区间最小值和他的位置之后 旋转最小值到root 这时他左子树的大小+1就是他现处位置 然后将i到最小值位置中间的区间打上标记等待旋转 这样全部处理完就okay了
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
const int M=100505,inf=1000000000;
int n,root,c[M][2],mn[M],pos[M],ans[M],rev[M],fa[M],size[M],v[M],top,s[M];
struct node{int v,pos;}tr[M];
bool cmp(node a,node b){return ((a.v<b.v)||(a.v==b.v&&a.pos<b.pos));}
bool operator<(node a,node b){return a.pos<b.pos;}
void push_up(int k){
    int l=c[k][0],r=c[k][1];
    size[k]=size[l]+size[r]+1;
    pos[k]=k; mn[k]=v[k];
    if(mn[l]<mn[k]){ mn[k]=mn[l]; pos[k]=pos[l];}
    if(mn[r]<mn[k]){ mn[k]=mn[r]; pos[k]=pos[r];}
}
void push_down(int k){
    int l=c[k][0],r=c[k][1];
    rev[k]=0; rev[l]^=1; rev[r]^=1;
    swap(c[k][0],c[k][1]);
}
int build(int l,int r){
    if(l>r) return 0;
    int m=(l+r)>>1; 
    size[m]=1; pos[m]=m; 
    c[m][0]=build(l,m-1);
    c[m][1]=build(m+1,r);
    for(int i=0;i<2;i++) if(c[m][i]) fa[c[m][i]]=m;
    push_up(m);
    return m;
}
int find(int x,int rank){
    if(rev[x]) push_down(x);
    int l=c[x][0],r=c[x][1];
    if(size[l]+1==rank) return x;
    else if(size[l]>=rank) return find(l,rank);
    else return find(r,rank-size[l]-1);
}
void rotate(int x,int &k){
    int y=fa[x],z=fa[y],l=0,r=1;
    if(c[y][1]==x) l=1,r=0;
    if(y==k) k=x;
    else{if(c[z][0]==y) c[z][0]=x; else c[z][1]=x;}
    fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
    c[y][l]=c[x][r]; c[x][r]=y;
    push_up(x); push_up(y);
}
void splay(int x,int &k){
    top=0;s[++top]=x;
    for(int i=x;fa[i];i=fa[i])
        s[++top]=fa[i];
    for(int i=top;i;i--)
        if(rev[s[i]]) push_down(s[i]);
    while(x!=k){
        int y=fa[x],z=fa[y];
        if(y!=k){
            if(c[z][0]==y^c[y][0]==x) rotate(y,k);
            else rotate(x,k);
        }
        rotate(x,k);
    }
}
int push_ans(int l,int r){
    int x=find(root,l),y=find(root,r+2);
    splay(x,root); splay(y,c[x][1]);
    return pos[c[y][0]];
}
void rever(int l,int r){
    int x=find(root,l),y=find(root,r+2);
    splay(x,root); splay(y,c[x][1]);
    rev[c[y][0]]^=1;
}
int main()
{
    n=read(); mn[0]=inf; 
    tr[1].v=tr[n+2].v=inf; 
    for(int i=2;i<=n+1;i++) tr[i].v=read(),tr[i].pos=i;
    sort(tr+2,tr+2+n,cmp);
    for(int i=2;i<=n+1;i++) tr[i].v=i-1;
    sort(tr+2,tr+2+n); for(int i=2;i<=n+1;i++) v[i]=tr[i].v;
    root=build(1,n+2); 
    for(int i=1;i<=n;i++){
        int x=push_ans(i,n);
        splay(x,root);
        ans[i]=size[c[x][0]];
        rever(i,ans[i]);
    }
    for(int i=1;i<=n;i++){ printf("%d",ans[i]); if(i!=n) printf(" ");}
    return 0;
}
View Code

 

bzoj1552

标签:nod   str   bzoj   open   getchar   ==   离散化   name   hid   

原文地址:http://www.cnblogs.com/lyzuikeai/p/6916557.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!