zoukankan      html  css  js  c++  java
  • 可持久化Trie

    咕了两天的内容

    和主席树的思想差不多,当前节点有的边就往下连,没有的边就连到之前的trie上

    最大异或和:https://www.luogu.org/problem/P4735

    处理前缀异或和,则问题为求p在[l - 1,r - 1]内,s[p] ^ (s[n] ^ x)的最大值

    考虑到右边是定值,转化为求区间内异或定值的最大值,可持久化Trie板子

    细节看代码

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef double db;
    #define llinf 9000000000000000000LL
    #define B cout << "breakpoint" << endl;
    #define O(x) cout << #x << "  "  << x << endl;
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1; 
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    const int maxn = 6e5 + 5;
    int sum[maxn],tot;
    int ch[maxn * 27][2],cnt[maxn * 27],rt[maxn];
    void insert(int a,int b,int t,int x)
    {
        if(t < 0) return;
        int i = (x >> t) & 1;
        ch[a][!i] = ch[b][!i];
        ch[a][i] = ++tot;
        cnt[ch[a][i]] = cnt[ch[b][i]] + 1;
        insert(ch[a][i],ch[b][i],t - 1,x);
    }
    int query(int a,int b,int t,int x)
    {
        if(t < 0) return 0;
        int i = (x >> t) & 1;
        if(cnt[ch[b][!i]] - cnt[ch[a][!i]] > 0)
            return (1 << t) + query(ch[a][!i],ch[b][!i],t - 1,x);
        else return query(ch[a][i],ch[b][i],t - 1,x);
    }
    int n,m;
    int main()
    {
        char op[5];
        int x,l,r;
        n = read(),m = read();
        rt[0] = ++tot;
        insert(rt[0],0,25,0);
        for(int i = 1;i <= n;i++)
        {
            x = read();
            sum[i] = sum[i - 1] ^ x;
            rt[i] = ++tot;
            insert(rt[i],rt[i - 1],25,sum[i]);
        }
        while(m--)
        {
            scanf("%s",op);
            if(op[0] == 'A')
            {
                x = read();
                n++;
                sum[n] = sum[n - 1] ^ x;
                rt[n] = ++tot;
                insert(rt[n],rt[n - 1],25,sum[n]);
            }
            else
            {
                l = read(),r = read(),x = read();
                l--,r--;
                if(l == 0) printf("%d
    ",query(0,rt[r],25,x ^ sum[n]));
                else printf("%d
    ",query(rt[l - 1],rt[r],25,x ^ sum[n]));
            }
        }
    }
    View Code

    异或粽子:https://www.luogu.org/problem/P5283

    时隔好久2333

    依旧套路处理前缀异或和,然后考虑固定右端点求出每个右端点最大值,放入堆中

    维护一个堆,每次把当前K大值取出来,加入答案,再向堆中扔入K+1大值

    如何求区间内异或定值的K大值也是板子,细节在代码

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef int mainint;
    #define int long long
    typedef double db;
    #define pii pair<int,int>
    #define mp make_pair
    #define llinf 9000000000000000000LL
    #define B cout << "breakpoint" << endl;
    #define O(x) cout << #x << "  "  << x << endl;
    inline int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1; 
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (ans *= 10) += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    const int maxn = 6e5 + 5;
    int sum[maxn],tot;
    int ch[maxn * 40][2],cnt[maxn * 40],rt[maxn],num[maxn];
    int n,k;
    void insert(int a,int b,int t,int x)
    {
        if(t < 0) return;
        int i = (x >> t) & 1;
        ch[a][!i] = ch[b][!i];
        ch[a][i] = ++tot;
        cnt[ch[a][i]] = cnt[ch[b][i]] + 1;
        insert(ch[a][i],ch[b][i],t - 1,x);
    }
    int query(int a,int b,int t,int x,int num)
    {
        if(t < 0) return 0;
        int i = (x >> t) & 1;
        int tp = cnt[ch[b][!i]] - cnt[ch[a][!i]];
        if(tp >= num)
            return (1ll << t) + query(ch[a][!i],ch[b][!i],t - 1,x,num);
        else return query(ch[a][i],ch[b][i],t - 1,x,num - tp);
    }
    mainint main()
    {
        ll ans = 0;
        n = read(),k = read();
        rt[0] = ++tot;
        insert(rt[0],0,34,0);
        for(int i = 1;i <= n;i++)
        {
            int x = read();
            sum[i] = sum[i - 1] ^ x;
            rt[i] = ++tot;
            insert(rt[i],rt[i - 1],34,sum[i]);
            num[i] = 1;
        }
        priority_queue<pii> q;
        for(int i = 1;i <= n;i++) q.push(mp(query(0,rt[i - 1],34,sum[i],num[i]),i));
        for(int i = 1;i <= k;i++)
        {
            int u = q.top().second;
            ans += q.top().first;
            q.pop();
            num[u]++;
            q.push(mp(query(0,rt[u - 1],34,sum[u],num[u]),u));
        }
        printf("%lld",ans);
    }
    View Code
  • 相关阅读:
    路由的添加和删除
    extjs中的tabpanle下的combobox提交问题
    Asp.net下from认证统一认证配置
    ASP.NET权限管理系统(FrameWork) 1.0.8 Release
    Web网站架构设计
    手机6120C 玩仙剑dos版
    Extjs 4.07 对类型定义引发的匹配问题
    Supesoft权限管理系统(FrameWork) 1.0.9 Release
    Google静态地图如何显示两点之间路线1(简单路线)
    Chrome不支持showModalDialog模态对话框和无法返回returnValue的问题
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/11253118.html
Copyright © 2011-2022 走看看