bzoj4864: [BeiJing 2017 Wc]神秘物质

这道题维护区间极差的最小值 只有长度为二的区间有贡献 这个可以尝试画一下 自己想想 这样之后维护的值有 区间最小值 区间最大值 以及区间内长度为二的区间差的最小值 区间大小 点本身的值。 注意要看你维护的区间差在区间左点还是右点 这在查询min的时候很重要 剩下的自己看把 代码不算长的了 虽然有点慢 换成结构体应该会快很多 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=250000,inf=0x3f3f3f3f;
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;
}
int n,m,root,sum;
int c[M][2],fa[M],size[M],mx[M],mn[M],mc[M],cha[M],v[M];
void up(int k)
{
    int l=c[k][0],r=c[k][1];
    size[k]=size[l]+size[r]+1;
    mx[k]=mn[k]=v[k],mc[k]=cha[k];
    if(l)   mx[k]=max(mx[l],mx[k]),mn[k]=min(mn[k],mn[l]),mc[k]=min(mc[k],mc[l]);
    if(r)   mx[k]=max(mx[r],mx[k]),mn[k]=min(mn[k],mn[r]),mc[k]=min(mc[k],mc[r]);
}
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[y]=x; fa[x]=z; fa[c[x][r]]=y;
    c[y][l]=c[x][r]; c[x][r]=y;
    up(y); up(x);
}
void sp(int x,int& k){
    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 find(int x,int rank){
    if(!x) return 0;
    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 find(r,rank-size[l]-1);
}
int build(int l,int r){
    if(l>r) return 0;
    int m=(l+r)>>1;
    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;
    up(m);
    return m;
}
int push_max(int l,int r){
    int x=find(root,l),y=find(root,r+2);
    sp(x,root); sp(y,c[x][1]);
    printf("%d\n",mx[c[y][0]]-mn[c[y][0]]);
}
int push_min(int l,int r){
    int x=find(root,l+1),y=find(root,r+2);
    sp(x,root); sp(y,c[x][1]);
    printf("%d\n",mc[c[y][0]]);
}
void insert(int k,int w){
    int x=find(root,k+1),y=find(root,k+2);
    sp(x,root); sp(y,c[x][1]);
    size[++sum]=1; mx[sum]=mn[sum]=v[sum]=w;  
    mc[sum]=cha[sum]=abs(v[sum]-v[x]); cha[y]=abs(v[y]-v[sum]);
    c[y][0]=sum; fa[sum]=y;
    up(y); up(x);
}
void merge(int k,int w){
    int x=find(root,k),y=find(root,k+3);
    sp(x,root); sp(y,c[x][1]);
    int p=c[y][0]; 
    c[p][0]=c[p][1]=0; mx[p]=mn[p]=v[p]=w;  
    mc[p]=cha[p]=abs(v[p]-v[x]); cha[y]=abs(v[y]-v[p]); size[p]=1;
    up(y); up(x);
}
int main()
{
    n=read(); m=read(); v[2]=read();
    for(int i=3;i<=n+1;i++) v[i]=read(),cha[i]=abs(v[i]-v[i-1]);
    sum=n+2;
    root=build(1,n+2);
    char ch[10];
    int x,y;
    while(m--){
        scanf("%s",ch); x=read(); y=read();
        if(ch[1]=='e') merge(x,y);
        else if(ch[0]=='i') insert(x,y);
        else if(ch[1]=='a') push_max(x,y);
        else if(ch[1]=='i') push_min(x,y);
    }
    return 0;
}
View Code

 

posted @ 2017-06-02 12:51  友人Aqwq  阅读(215)  评论(0编辑  收藏  举报