• 【可持久化Trie】【set】bzoj3166 [Heoi2013]Alo


    枚举每个数,计算以其为次大数的最大区间,显然,只需要用这个区间的答案 对 答案进行更新即可。

    找到每个数右侧、左侧第1、2个比它大的数,然后分类讨论一下即可。

    找到的过程中把数sort以后,从大到小把它们的位置插入set,稍微维护一下即可。

    #include<cstdio>
    #include<algorithm>
    #include<set>
    using namespace std;
    #define N 50001
    #define MAXBIT 30
    set<int>T;
    typedef set<int>::iterator ER;
    int root[N],ch[N*(MAXBIT+1)][2],sz[N*(MAXBIT+1)],tot;
    int query(int L,int R,int W)//询问a[L...R]中W与其的最大异或值
    {
        int ans=0;
        L=root[L-1];R=root[R];
        for(int i=MAXBIT-1;i>=0;--i)
          {
            int Bit=(W>>i&1^1);
            if(sz[ch[R][Bit]]-sz[ch[L][Bit]]==0)
              Bit^=1;
            else
              ans+=1<<i;
            R=ch[R][Bit];
            L=ch[L][Bit];
          }
        return ans;
    }
    void add(int now,int W)//先add(0,0),再add(1...n,a[1...n])
    {
        int old=root[now-1];
        root[now]=++tot;
        now=root[now];
        for(int i=MAXBIT-1;i>=0;--i)
          {
            int Bit=(W>>i&1);
            sz[now]=sz[old]+1;
            ch[now][Bit^1]=ch[old][Bit^1];
            ch[now][Bit]=++tot;
            now=ch[now][Bit];
            old=ch[old][Bit];
          }
        sz[now]=sz[old]+1;
    }
    int n,ans,b[N],Ls[N],LLs[N],Rs[N],RRs[N];
    struct Point{int x,y;};
    bool operator < (const Point &a,const Point &b){return a.x<b.x;}
    Point a[N];
    int main()
    {
    	scanf("%d",&n);
    	add(0,0);
    	for(int i=1;i<=n;++i)
    	  {
    	  	scanf("%d",&a[i].x);
    	  	add(i,a[i].x);
    	  	a[i].y=i; b[i]=a[i].x;
    	  }
    	sort(a+1,a+n+1);
    	for(int i=n;i>=1;--i)
    	  {
    	  	T.insert(a[i].y);
    	  	ER it=T.find(a[i].y);
    	  	if(it!=T.begin())
    	  	  {
    			--it;
    			Ls[a[i].y]=*it;
    			if(it!=T.begin())
    			  {
    			  	--it;
    			  	LLs[a[i].y]=*it;
    			  	++it;
    			  }
    			++it;
    		  }
    	  	if((++it)!=T.end())
    	  	  {
    			Rs[a[i].y]=*it;
    			if((++it)!=T.end())
    			  RRs[a[i].y]=*it;
    			else
    			  RRs[a[i].y]=n+1;
    		  }
    		else
    		  Rs[a[i].y]=RRs[a[i].y]=n+1;
    	  }
    	for(int i=1;i<=n;++i)
    	  {
    	  	if(Ls[i])
    	  	  ans=max(ans,query(LLs[i]+1,Rs[i]-1,b[i]));
    	  	else if(RRs[i]!=n+1)
    	  	  ans=max(ans,query(1,RRs[i]-1,b[i]));
    	  	if(Rs[i]!=n+1)
    	  	  ans=max(ans,query(Ls[i]+1,RRs[i]-1,b[i]));
    	  	else if(LLs[i])
    	  	  ans=max(ans,query(LLs[i]+1,n,b[i]));
    	  }
    	printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    多变的鸭子策略模式
    反序列化和序列化
    UBUNTU eclipse必须是 jdk5.0以上
    Ubuntu Linux:MySQL安装指南
    phpMyAdmin下载、安装和使用入门
    读者-写者问题
    wget用法2
    在linux下安装mysql
    linux下数字转成字符串
    [SQLServer]必须知道的SQL
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4319673.html
Copyright © 2020-2023  润新知