zoukankan      html  css  js  c++  java
  • 线性基 + 并查集

    给一个1-base数组{a},有N次操作,每次操作会使一个位置无效。一个区间的权值定义为这个区间里选出一些数的异或和的最大值。求在每次操作前,所有不包含无效位置的区间的权值的最大值。

    输入描述:

    第一行读入一个正整数(1 <= n <= 105)

    第二行读入n个正整数,第i个表示a[i](0<= a[i] <= 109)

    第三行读入n个正整数,第i个表示x[i]即第i次操作的位置,保证x[i]互不相同。

    输出描述:

    输出n行答案
    示例1

    输入

    10
    169 816 709 896 58 490 97 254 99 796 
    4 2 3 10 5 6 1 8 9 7

    输出

    1023
    994
    994
    994
    490
    490
    254
    254
    99
    97

    题意 : 每次让一个位置得数失效,求解连续区间上异或值最大得是多少?
    思路分析 : 每次让一个位置失效,那么这个问题就可以逆向去考虑,每次加一个数,这个总比删除操作好处理,用并查集就可以,然后就是一个在套一个线性基就可以
    代码示例 :
    #define ll long long
    const int maxn = 1e5+5;
    const int mod = 1e9+7;
    const double eps = 1e-9;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    
    int n;
    int pre[maxn], pos[maxn];
    int f[maxn];
    int val[maxn][40];
    int an[maxn];
    
    int fid(int x){
        if (x != f[x]) f[x] = fid(f[x]);
        return f[x];
    }
    
    void insert(int b[], int x){
        for(int i = 30; i >= 0; i--){
            if (x>>i&1){
                if (!b[i]) {b[i] = x; break;}
                else x ^= b[i];
            }
        }
    }
    
    void unit(int p1, int p2){
        int x = fid(p1), y = fid(p2);
        for(int i = 0; i <= 30; i++){
            if (val[y][i]) insert(val[x], val[y][i]);
        }
        f[y] = x;
    }
    
    int solve(int p){
        int ans = 0;
        for(int i = 30; i >= 0; i--){
            if ((ans^val[p][i]) > ans) {
                ans ^= val[p][i];
            }
        }
        return ans;
    }
    
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        cin >> n;
        
        for(int i = 1; i <= n; i++) scanf("%d", &pre[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &pos[i]);
        memset(f, 0, sizeof(f));
        int ans = 0;
        for(int i = n; i >= 1; i--){
            int x = pos[i]; // 位置
            f[x] = x;
            insert(val[x], pre[x]);
            
            if (f[x-1]) unit(x, x-1);
            if (f[x+1]) unit(x, x+1);
            ans = max(ans, solve(x));
            an[i] = ans;
        }    
        for(int i = 1; i <= n; i++) printf("%d
    ", an[i]);
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    新概念第二册(1)--英语口语听力课1
    外企面试课程(一)---熟悉常见的缩略词
    公司 邮件 翻译 培训 长难句 结课
    workflow
    公司 邮件 翻译 培训 长难句 20
    公司 邮件 翻译 培训 长难句 19
    Engineering Management
    公司 邮件 翻译 培训 长难句 18
    公司 邮件 翻译 培训 长难句 17
    第14.5节 利用浏览器获取的http信息构造Python网页访问的http请求头
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8964278.html
Copyright © 2011-2022 走看看