zoukankan      html  css  js  c++  java
  • BZOJ 4864 [BJWC2017]神秘物质 (splay)

    题目大意:

    让你维护一个序列,支持:

    1.合并两个相邻的数为一个新的数

    2.在某个位置插入一个数

    3.查询一个区间的任意子区间极差的最大值

    4.查询一个区间的任意子区间极差的最小值

    前两个操作可以用$splay$轻松实现

    第三个操作,求区间的子区间极差最大值,额外维护子树内元素最大值最小值即可

    第四个操作,求区间的子区间极差最小值

    显然,我们选择的子区间越长,极差越大

    所以极差最小的子区间一定是相邻的两个数构成的区间

    维护一个$lb_{x},rb_{x}$,表示它前/后一个数和它差值的绝对值,每次插入/合并操作时修改这个值即可

    再维护一个$ms_{x}$,表示子树内所有节点的$lb_{x},rb_{x}$最小值,注意,它不是x子树代表的区间的极差最小值,是$[L-1,R+1]$的

    所以询问长度为2时需要特判

    注意最大值inf不要开小了!

    建议自己写个暴力和数据生成器对拍,这种题不拍简直找死

      1 #include <queue>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N1 201000
      7 #define S1 (N1<<1)
      8 #define T1 (N1<<2)
      9 #define ll long long
     10 #define uint unsigned int
     11 #define rint register int 
     12 #define ull unsigned long long
     13 #define dd double
     14 #define il inline 
     15 #define inf 1000000000
     16 using namespace std;
     17 
     18 int gint()
     19 {
     20     int ret=0,fh=1;char c=getchar();
     21     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     22     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     23     return ret*fh;
     24 }
     25 int n,m,T;
     26 int a[N1];
     27 int Abs(int x){return x>0?x:-x;}
     28 struct Splay{
     29 #define root ch[0][1]
     30 int ch[N1][2],fa[N1],sz[N1],mi[N1],ma[N1],tot;
     31 int ms[N1],val[N1],lb[N1],rb[N1];
     32 void init(){mi[0]=ms[0]=inf;tot=n+2;}
     33 int idf(int x){return ch[fa[x]][0]==x?0:1;}
     34 int cre(int w){tot++,val[tot]=mi[tot]=ma[tot]=w;return tot;}
     35 void con(int x,int ff,int p){fa[x]=ff,ch[ff][p]=x;}
     36 void des(int x){fa[x]=ma[x]=val[x]=ch[x][0]=ch[x][1]=0,mi[x]=ms[x]=lb[x]=rb[x]=inf;}
     37 void pushup(int x)
     38 {
     39     int ls=ch[x][0],rs=ch[x][1]; ma[x]=mi[x]=val[x]; ms[x]=min(lb[x],rb[x]);
     40     if(ls) ma[x]=max(ma[x],ma[ls]), mi[x]=min(mi[x],mi[ls]), ms[x]=min(ms[x],ms[ls]);
     41     if(rs) ma[x]=max(ma[x],ma[rs]), mi[x]=min(mi[x],mi[rs]), ms[x]=min(ms[x],ms[rs]);
     42     sz[x]=sz[ls]+sz[rs]+1;
     43 }
     44 void rot(int x)
     45 {
     46     int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
     47     fa[ch[x][px^1]]=y,ch[y][px]=ch[x][px^1];
     48     ch[x][px^1]=y,fa[y]=x,ch[ff][py]=x,fa[x]=ff;
     49     pushup(y),pushup(x);
     50 }
     51 void splay(int x,int to)
     52 {
     53     to=fa[to];int y;
     54     while(fa[x]!=to)
     55     {
     56         y=fa[x];
     57         if(fa[y]==to) rot(x);
     58         else if(idf(y)==idf(x)) rot(y),rot(x);
     59         else rot(x),rot(x);
     60     }
     61 }
     62 int find(int K)
     63 {
     64     int x=root;
     65     while(1)
     66     {
     67         if(K>sz[ch[x][0]]){
     68             K-=sz[ch[x][0]];
     69             if(K==1) return x;
     70             K--; x=ch[x][1];
     71         }else{
     72             x=ch[x][0];
     73         }
     74     }
     75 }
     76 int split(int l,int r)
     77 {
     78     int x=find(l); splay(x,root);
     79     int y=find(r+2);splay(y,ch[x][1]);
     80     return ch[y][0];
     81 }
     82 void Merge(int K,int w)
     83 {
     84     int x=split(K,K+1),f=root,y=ch[f][1];
     85     val[x]=w;
     86     if(ch[x][0]) des(ch[x][0]),ch[x][0]=0;
     87     if(ch[x][1]) des(ch[x][1]),ch[x][1]=0;
     88     rb[f]=lb[x]=Abs(w-val[f]);
     89     rb[x]=lb[y]=Abs(w-val[y]);
     90     pushup(x),pushup(y),pushup(f);
     91 }
     92 void Ins(int K,int w)
     93 {
     94     int x=split(K,K),y=ch[root][1],z=cre(w);
     95     con(z,x,1);
     96     rb[x]=lb[z]=Abs(w-val[x]);
     97     rb[z]=lb[y]=Abs(w-val[y]);
     98     pushup(z),pushup(x),pushup(y);
     99 }
    100 int Query_max(int L,int R)
    101 {
    102     int x=split(L,R);
    103     return ma[x]-mi[x];
    104 }
    105 int Query_min(int L,int R)
    106 {
    107     int x;
    108     if(R-L<=1){
    109         x=split(L,R-1);
    110         return rb[x];
    111     }else{
    112         x=split(L+1,R-1);
    113         return ms[x];
    114     }
    115 }
    116 int Build(int *a,int l,int r,int ff)
    117 {
    118     if(l>r) return 0;
    119     int mid=(l+r)>>1,x=mid+1; fa[x]=ff; val[x]=a[mid]; 
    120     lb[x]=(mid==0)?inf:Abs(a[mid]-a[mid-1]);
    121     rb[x]=(mid==n+1)?inf:Abs(a[mid]-a[mid+1]);
    122     ch[x][0]=Build(a,l,mid-1,x);
    123     ch[x][1]=Build(a,mid+1,r,x);
    124     pushup(x); return x;
    125 }
    126 #undef root
    127 }s;
    128 char str[10];
    129 
    130 int main()
    131 {
    132     //freopen("t2.in","r",stdin);
    133     scanf("%d%d",&n,&m);
    134     int i,x,y,z,cnt=0,de; s.init();
    135     for(i=1;i<=n;i++) a[i]=gint();
    136     a[0]=inf; a[n+1]=inf;
    137     s.ch[0][1]=s.Build(a,0,n+1,0);
    138     for(i=1;i<=m;i++)
    139     {
    140         scanf("%s",str); 
    141         x=gint(); y=gint(); 
    142         if(str[1]=='e'){
    143             s.Merge(x,y);
    144         }else if(str[1]=='n'){
    145             s.Ins(x,y);
    146         }else if(str[1]=='a'){
    147             /*cnt++;
    148             if(cnt==957)
    149                 de=1;*/
    150             printf("%d
    ",s.Query_max(x,y));
    151         }else{
    152             printf("%d
    ",s.Query_min(x,y));
    153         }
    154     }
    155     return 0;
    156 }
  • 相关阅读:
    spring data jpa 动态查询(mysql)
    C#面向对象15 多态
    Visual Studio 2012网站如何只生成一个DLL文件
    C#面向对象14 List泛型集合/装箱和拆箱/字典集合(Dictionary)
    C#面向对象13 文件类操作 Path/File/FileStream
    C#面向对象12 集合
    C#面向对象11 里氏转换
    C#面向对象10 继承
    C#面向对象9 字符串
    C# 面向对象8 值类型和引用类型
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10160309.html
Copyright © 2011-2022 走看看