• MAXOR


    前言

    边界条件,烦人!(╯‵□′)╯︵┻━┻

    题目

    SPOJ

    洛谷(有中文题面)

    一句话题意:区间询问子区间异或和最大值。

    讲解

    其实做法很简单,将 (a_i) 做一个前缀异或和,然后分块+可持久化Trie就行了。

    但是我们注意这样一个问题:如果我们要表示一个区间 ([l,r]) 的异或和,我们需要用 (a_{l-1}oplus a_{r}),对应到Trie上,(l-1) 是要被包含的,所以我们传的两个根应该是 (rt_{l-2},rt_r)

    显然会有越界的问题,我最开始想的是在前面放个 (0),但是这样写很麻烦。而且我没调出来

    但其实这种边界用 (a_{l-1})([l,r]) 即可。

    代码

    //12252024832524
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 12005;
    const int MAXB = 150;
    int n,m,B,ans;
    int a[MAXN];
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int ID(int x){return (x-1)/B;}
    int FI[MAXN];
    
    int tot,rt[MAXN];
    struct Trie
    {
    	int ch[2],cnt;
    }t[MAXN * 32];
    int newnode(){++tot;t[tot].ch[0] = t[tot].ch[1] = t[tot].cnt = 0;return tot;}
    void Add(int lst,int &x,int val,int rk)
    {
    	if(!x || x == lst) x = newnode(),t[x] = t[lst];
    	++t[x].cnt;
    	if(rk < 0) return;
    	bool to = val >> rk & 1;
    	Add(t[lst].ch[to],t[x].ch[to],val,rk-1);
    }
    int Query(int lst,int x,int val,int rk,int s)
    {
    	if(rk < 0) return s;
    	bool to = (val >> rk & 1) ^ 1;
    	if(t[t[x].ch[to]].cnt-t[t[lst].ch[to]].cnt) return Query(t[lst].ch[to],t[x].ch[to],val,rk-1,s|(1<<rk));
    	else return Query(t[lst].ch[to^1],t[x].ch[to^1],val,rk-1,s);
    }
    int MAX[MAXB][MAXB];
    
    int main()
    {
    //	freopen("data.in","r",stdin);
    //	freopen("mine.out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 1;i <= n;++ i) Add(rt[i-1],rt[i],a[i] = a[i-1]^Read(),30);
    	B = ceil(sqrt(1.0*n*n/m/2));
    	for(int i = 1;i <= n;i += B)
    	{
    		int now = 0;
    		FI[ID(i)] = i;
    		for(int j = i;j <= n;++ j)
    		{
    			now = Max(now,Query(rt[i-1],rt[j-1],a[j],30,0));
    			now = Max(now,a[j]^a[i-1]);
    			if((ID(j)^ID(j+1)) || j == n) MAX[ID(i)][ID(j)] = now;
    		}
    	}
    	while(m --> 0)
    	{
    		int x = Read(),y = Read();
    		int L = (x+0ll+ans)%n+1,R = (y+0ll+ans)%n+1;
    		int l = Min(L,R),r = Max(L,R);
    		if(ID(l)+1 >= ID(r))
    		{
    			ans = Query(rt[l-1],rt[r],a[l-1],30,0);
    			for(int i = l;i <= r;++ i) ans = Max(ans,Query(rt[l-1],rt[i-1],a[i],30,0));
    			Put(ans,'
    ');
    		}
    		else
    		{
    			L = ID(l)+1,R = ID(r)-1;
    			ans = MAX[L][R];
    			L = FI[L];
    			ans = Max(ans,Query(rt[l-1],rt[r],a[l-1],30,0));
    			for(int i = l;i < L;++ i) ans = Max(ans,Query(rt[l-1],rt[r],a[i],30,0));
    			for(int i = FI[ID(r)];i <= r;++ i) ans = Max(ans,Query(rt[l-1],rt[i],a[i],30,0));
    			Put(ans,'
    ');
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    图片自动播放
    选项卡切换
    jquery实现全选、反选、不选
    JQuery $()后面的括号里的内容什么时候加引号,什么时候不加
    ajax跨域jsonp
    加班与效率
    提问的智慧
    程序员要勇于说不
    编程从业五年的十四条经验,句句朴实
    成为高效程序员的7个重要习惯
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15291262.html
Copyright © 2020-2023  润新知