计蒜客1264:求序列完美度(01字典树)

传送门

题意

分析

01字典树,每次插入所有数,按顺序删除查询,按题目要求更新答案即可
学习了一种新的query写法

trick

1.不理解我的code的错误

代码

//wa
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e3+10;//集合中的数字个数
int ch[30*maxn][2];//节点的边信息
int num[30*maxn];//记录节点的使用次数,删除时要用
//int val[32*maxn];//节点存储的值
int cnt;//树中节点的个数

int t,n,ans,l,r,z;
int a[1010];

inline void init()
{
    cnt=1;mem(ch[0],0);//清空树
}

void insert(int x)//在字典树中插入x,和一般字典树操作相同,将x化成二进制插入到字典树
{
    int cur=0;
    for(int i=29;i>=0;--i)
    {
        int idx=((x>>i)&1);
        if(!ch[cur][idx])
        {
            mem(ch[cnt],0);
            num[cnt]=0;
            ch[cur][idx]=cnt++;
            //val[cnt++]=0;
        }
        //printf("ch[%d][%d]=%d\n",cur,idx,ch[cur][idx]);
        cur=ch[cur][idx];
        num[cur]++;
    }
    //val[cur]=x;//最后节点插入val
}

void update(int x)
{
    int cur=0;
    for(int i=29;i>=0;--i)
    {
        int idx=((x>>i)&1);
        cur=ch[cur][idx];
        num[cur]--;
    }
}

/*
ll query(ll x)//在字典树(数集)中查找和x异或是最大值的元素y,返回y
{
    int cur=0;
    for(int i=32;i>=0;--i)
    {
        int idx=(x>>i)&1;
        if(ch[cur][idx^1]) cur=ch[cur][idx^1];else cur=ch[cur][idx];
    }
    return val[cur];
}
*/
/*
int query(int x)//在字典树(数集)中查找和x异或是最大值的元素y,返回异或的最大值
//带删除操作的查询
{
    int cur=0;
    for(int i=32;i>=0;--i)
    {
        int idx=(x>>i)&1;
        if(ch[cur][idx^1]&&num[ch[cur][idx^1]]) cur=ch[cur][idx^1];else cur=ch[cur][idx];
    }
    //printf("val(%d)=%d\n",cur,val[cur]);
    return val[cur]^x;
}
*/
int get_ans(int x)
{
    int cur=0,ret=0;
    for(int i=29;i>=0;--i)
    {
        int idx=(((x>>i)&1)^1);
        if(num[ch[cur][idx]]) cur=ch[cur][idx],ret|=(1<<i);
        else cur=ch[cur][idx^1];    
    }
    return ret;
}
void solve(int p)
{
    init();
    F(i,1,n) insert(a[i]);
    int sum=0;
    F(i,p,n)
    {
        update(a[i]);
        sum+=a[i];
        int ret=get_ans(sum);
        if(ret>ans) ans=ret,l=p,r=i,z=sum^ret;
        else if(ret==ans)
        {
            if(p<l) l=p,r=i,z=sum^ret;
            else if(p==l&&i<r) r=i,z=sum^ret;
        }
    }
}
int main()
{
    for(scanf("%d",&t);t--;)
    {
        scanf("%d",&n);
        F(i,1,n) scanf("%d",a+i);
        ans=-1;
        F(i,1,n) solve(i);
        printf("%d %d %d %d\n",l,r,z,ans);
    }
    return 0;
}
//ac
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n,a[maxn];
struct node
{
    int l,r,x,mx;
}ans;
int ch[maxn*30][2],sz,val[maxn*30];
void insert(int x)
{
    int u=0;
    for(int i=29;i>=0;i--)
    {
        int c=((x>>i)&1);
        if(!ch[u][c])
        {
            memset(ch[sz],0,sizeof(ch[sz]));
            val[sz]=0;
            ch[u][c]=sz++;
        }
        u=ch[u][c];
        val[u]++;
    }
}
inline void del(int x)
{
    int u=0;
    for(int i=29;i>=0;i--)
    {
        int c=((x>>i)&1);
        u=ch[u][c];
        val[u]--;
    }
}
int get_ans(int x)
{
    int u=0,tep=0;
    for(int i=29;i>=0;i--)
    {
        int c=(((x>>i)&1)^1);
        if(val[ch[u][c]])u=ch[u][c],tep|=(1<<i);
        else u=ch[u][c^1];
    }
    return tep;
}
inline void init()
{
    sz=1;memset(ch[0],0,sizeof(ch[0]));
    for(int i=1;i<=n;i++)insert(a[i]);
}
inline void solve(int p)
{
    init();
    int sum=0;
    for(int i=p;i<=n;i++)
    {
        del(a[i]);
        sum+=a[i];
        int g=get_ans(sum);
        if(g>ans.mx)ans.mx=g,ans.l=p,ans.r=i,ans.x=sum^g;
        else if(g==ans.mx)
        {
            if(p<ans.l)ans.l=p,ans.r=i,ans.x=sum^g;
            else if(p==ans.l&&i<ans.r)ans.r=i,ans.x=sum^g;
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        ans.mx=-1;
        for(int i=1;i<=n;i++)solve(i);
        printf("%d %d %d %d\n",ans.l,ans.r,ans.x,ans.mx);
    }
    return 0;
}
posted @ 2017-07-07 16:39  遗风忘语  阅读(259)  评论(0编辑  收藏  举报