• [HEOI2013]ALO


    https://zybuluo.com/ysner/note/1238170

    题面

    现在你拥有(n)颗宝石,每颗宝石有一个能量密度,记为(a_i)。现在你可以选取连续的一些宝石(必须多于一个)进行融合,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值与其他任意一颗宝石的能量密度按位异或的值
    现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大。

    • (nleq5*10^4)

    题面

    显然要可持久化(Trie)树。
    唯一有点费脑子的地方是次大值

    在一个区间找次大值会把复杂度弄得很鬼。
    换个角度想,如果枚举次大值,则有两种情况:

    • 最大值在左边,右边数都比次大值小(右端点右一个比次大值大)
    • 最大值在右边,左边数都比次大值小(左端点左一个比次大值小)

    实际上我们可以用链表维护大小关系。
    (a_i)从小到大枚举,用完这个数就把它删掉,这样左右端就是两个比它大的数,可以(O(1))确定区间左右端点。
    于是分情况统计答案即可。
    不加rt调1h系列

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #define re register
    #define il inline
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define fp(i,a,b) for(re int i=a;i<=b;i++)
    #define fq(i,a,b) for(re int i=a;i>=b;i--)
    using namespace std;
    const int mod=1e9+7,N=1e5+100;
    struct dat{int w,id;bool operator < (const dat &o) const {return w<o.w;}}a[N];
    int ysn,sum[N*50],t[N*50][2],l[N],r[N],ans,n,rt[N*50];
    il ll gi()
    {
       re ll x=0,t=1;
       re char ch=getchar();
       while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
       if(ch=='-') t=-1,ch=getchar();
       while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
       return x*t;
    }
    il void Build(re int x,re int &y,re int w,re int dep)
    {
      sum[y=++ysn]=sum[x]+1;
      if(dep<0) return;
      re int p=(w>>dep)&1;
      t[y][p^1]=t[x][p^1];
      Build(t[x][p],t[y][p],w,dep-1);
    }
    il int Query(re int x,re int y,re int w,re int dep)
    {
      if(dep<0) return 0;
      re int p=(w>>dep)&1,tmp=sum[t[y][p^1]]-sum[t[x][p^1]];
      if(tmp) return (1<<dep)+Query(t[x][p^1],t[y][p^1],w,dep-1);
      else return Query(t[x][p],t[y][p],w,dep-1);
    }
    int main()
    {
      n=gi();
      fp(i,1,n) a[i].w=gi(),a[i].id=i,l[i]=i-1,r[i]=i+1,Build(rt[i-1],rt[i],a[i].w,30);
      sort(a+1,a+1+n);
      fp(i,1,n)
        {
          re int x=a[i].id,z=l[x],y=r[x];
          r[z]=y;l[y]=z;
          if(z) ans=max(ans,Query(rt[l[z]],rt[y-1],a[i].w,30));
          if(y<=n) ans=max(ans,Query(rt[z],rt[r[y]-1],a[i].w,30));
        }
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    SQLServer.Produce的研究
    petshop以异步方式插入订单的疑惑(后面理解了)
    SQLHelper.GetCachedParameters方法之缓存
    DALFactory抽象工厂理解
    petshop异时消息处理队列抽象工厂
    AJAX学习2(经典)
    对SQLServerDAL.order的研究(不错,有心得)
    Invertory类对商品库存的更新困惑解决了
    AJAX学习1
    用DataSet读取xml文件
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9417089.html
Copyright © 2020-2023  润新知