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;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    QueryRunner查询返回值为int的数据
    c3p0连接池获取数据库连接
    javascript-文件File转换成base64格式
    php 判断是否手机端还是pc端
    MySql -- 数据结构
    tp5--路由的使用方法(深入)
    tp5--路由的使用(初级)
    tp5--开发规范
    二维数组排序 按某个字段排序
    文件记录网页访问量
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8964278.html
Copyright © 2011-2022 走看看