【Wannafly挑战赛14 E】无效位置(并查集思想+线性基合并)

博客围绕牛客网一道题目展开,题目要求在每次操作前求所有不包含无效位置的区间权值最大值。解题思路是采用逆操作,对线性基进行合并,同时运用并查集思想,记录左右两边‘位置无效’的最远下标,合并线性基并记录最大异或值,最后倒数输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:https://ac.nowcoder.com/acm/contest/81/E?&headNav=www
来源:牛客网

题目:


题目描述

给一个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

解题思路:


每次某个位置无效后都会将这n个数划分成多个段,有些数要从线性基中删除。从线性基中删除数字不易,但是可以对线性基进行合并,所以需要逆操作,即对于样例,处理时无效位置的顺序是7 9 8 1  6 5 10 3 2 4

同时这道题还需要用到并查集的思想,用l[pos],r[pos]记录当前pos左右两边“位置无效”所能达到的最远下标

拿样例来说明:(位置无效说明该位置上数被删除了)

i12345678910
a[i]169816709896584909725499796
程序处理时删除的顺序49810651327

“程序处理时删除的顺序”越大实际上在正序执行题目要求时越先被删除。

left=l[pos],right=r[pos],每次都让【left】下的线性基和【pos+1】下的线性基进行合并,得到新的【left】下的线性基(并查集思想)

并记录【left】下的线性基的最大异或值,和上一次求得的其他区间的最大异或值比较,取最大值。

最后倒数输出这些记录的结果。

参照代码模拟一下吧,语言表达能力受限,表述得不太明白。

这道题,max_base不可以设成32,可以设成31,30,1e9是30位的

ac代码:


#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
const int max_base=30;
typedef long long ll;
int a[maxn],x[maxn],ans[maxn],l[maxn],r[maxn],vis[maxn];
int xian[maxn][max_base+3]={0};//存线性基,用到并查集的思想
int n;
void solve()
{
    //倒序删除
    for(int i=1;i<=n;i++)
    {
        int pos=x[n-i+1],left=pos,right=pos;//倒序
        vis[pos]=1;
        if(l[pos-1]) left=l[pos-1];
        if(r[pos+1]) right=r[pos+1];
        l[pos]=left,r[pos]=right;
        r[left]=right,l[right]=left;//[l[pos],r[pos]]表示pos所在的最大的区间,该区间内的数表示的位置都是无效的

        int p=a[pos];//当前位置pos无效,pos位置上对应的数

        for(int j=max_base;j>=0;j--)
        {
            if(p>>j&1)
            {
                if(xian[left][j])
                    p^=xian[left][j];
                else
                {
                    xian[left][j]=p;
                    break;
                }
            }
        }
        //线性基合并
        if(vis[pos+1])//对于全0的线性基无需合并
        {
             for(int k=max_base;k>=0;k--)
             {
                 for(int j=max_base;j>=0;j--)
                 {
                     if(xian[pos+1][k]>>j&1)//将pos+1对应的线性基中j位为1的数合并到left对应的线性基中
                     {
                         if(xian[left][j])
                             xian[pos+1][k]^=xian[left][j];
                         else
                         {
                             xian[left][j]=xian[pos+1][k];
                             break;
                         }
                     }
                 }
             }
        }
        ans[i]=0;
        for(int j=max_base;j>=0;j--)
            if(xian[left][j]) ans[i]=max(ans[i],ans[i]^xian[left][j]);
        //当某个位置无效时可以分割出多个段,上面的循环只是计算出了left所对应的区间段的最大异或值,还要和其他段的异或值值比较
        ans[i]=max(ans[i],ans[i-1]);
    }
}
int main() {
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&x[i]);
    solve();
    for(int i=n;i>=1;i--)
        printf("%d\n",ans[i]);
    return 0;
}

 

1. 用户与权限管理模块 角色管理: 学生:查看实验室信息、预约设备、提交耗材申请、参与安全考核 教师:管理课题组预约、审批学生耗材申请、查看本课题组使用记录 管理员:设备全生命周期管理、审核预约、耗材采购与分发、安全检查 用户操作: 登录认证:统一身份认证(对接学号 / 工号系统,模拟实现),支持密码重置 信息管理:学生 / 教师维护个人信息(联系方式、所属院系),管理员管理所有用户 权限控制:不同角色仅可见对应功能(如学生不可删除设备信息) 2. 实验室与设备管理模块 实验室信息管理: 基础信息:实验室编号、名称、位置、容纳人数、开放时间、负责人 功能分类:按学科(计算机实验室 / 电子实验室 / 化学实验室)标记,关联可开展实验类型 状态展示:实时显示当前使用人数、设备运行状态(正常 / 故障) 设备管理: 设备档案:名称、型号、规格、购置日期、单价、生产厂家、存放位置、责任人 全生命周期管理: 入库登记:管理员录入新设备信息,生成唯一资产编号 维护记录:记录维修、校准、保养信息(时间、内容、执行人) 报废处理:登记报废原因、时间,更新设备状态为 "已报废" 设备查询:支持按名称、型号、状态多条件检索,显示设备当前可用情况 3. 预约与使用模块 预约管理: 预约规则:学生可预约未来 7 天内的设备 / 实验室,单最长 4 小时(可设置) 预约流程:选择实验室→选择设备→选择时间段→提交申请(需填写实验目的) 审核机制:普通实验自动通过,高危实验(如化学实验)需教师审核 使用记录: 签到 / 签退:到达实验室后扫码签到,离开时签退,系统自动记录实际使用时长 使用登记:填写实验内容、设备运行情况(正常 / 异常),异常情况需详细描述 违规管理:迟到 15 分钟自动取消预约,多违规限制预约权限 4. 耗材与安全管理模块 耗材管理: 耗材档案:名称、规格、数量、存放位置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值