comet oj #3 D 区间维护异或后的线性基

这不是原题吗...

具体做法参考codefores 587 E

不过这题卡常...

写题解纯粹是为了记录一下快读...

#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define rep(ii,a,b) for(register int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(register int ii=b;ii>=a;--ii)
using namespace std;
const int maxn=5e4+10,maxm=2e5+10;
int casn,n,m,k,val[maxn],curpos = 0, iseof;
struct bass{
  int flag,val;
  int d[33];
  inline void init(){val=flag=0;memset(d,0,sizeof d);}
  inline void insert(ll x){
    for(register int i=30;x&&i>=0;--i)
        if(x&(1ll<<i)){
          if(!d[i]) {d[i]=x;return;}
          else x^=d[i];
        }
  }
  inline int query(int x){
    register int ans=x;
    per(i,0,30){
      if((ans^d[i])>ans) {
        ans^=d[i];
      }
    }
    return ans;
  }
  inline void update(int x){val^=x;flag^=x;}
};
namespace segtree{
  #define nd node[now]
  #define ndl node[now<<1]
  #define ndr node[now<<1|1]
  inline bass marge(bass &a,bass b) {
    bass ans;ans.init();
    per(i,0,30) ans.insert(a.d[i]),ans.insert(b.d[i]);
    ans.insert(a.val^b.val);
    ans.val=a.val;
    return ans;
  }
  bass node[maxn<<2|3];
  inline void down(int now){
    if(nd.flag){
      ndl.update(nd.flag);ndr.update(nd.flag);
      nd.flag=0;
    }
  }
  void maketree(int s,int t,int now=1){
    nd.init();
    if(s==t) {nd.val=val[s];return ;}
    maketree(s,(s+t)/2,now<<1);
    maketree((s+t)/2+1,t,now<<1|1);
    nd=marge(ndl,ndr);
  }
  void update(int s,int t,int x,int l,int r,int now=1){
    if(s<=l&&t>=r) {nd.update(x);return;}
    down(now);int mid=(l+r)/2;
    if(s<=mid) update(s,t,x,l,mid,now<<1);
    if(t>mid) update(s,t,x,mid+1,r,now<<1|1);
    nd=marge(ndl,ndr);
  }
  bass ans;
  void query(int s,int t,int l,int r,int now=1){
    if(s<=l&&t>=r) {
        ans=marge(ans,nd);
        return ;
    }
    down(now);int mid=(l+r)/2;
    if(s<=mid) query(s,t,l,mid,now<<1);
    if(t>mid) query(s,t,mid+1,r,now<<1|1);
  }
}
inline void write(int x) {if(x>9) write(x / 10);putchar(x % 10 + ‘0‘);}
char buf[100 * 1024 * 1024 + 5];
int nxint() {
  if (iseof) return 0;
  register int ret = 0,flg = 0;
  while (!(‘0‘ <= buf[curpos] && buf[curpos] <= ‘9‘)) {
    if (buf[curpos] == 0) {
      if (fgets(buf, 16 * 1024 * 1024, stdin) == NULL) iseof = true;
      curpos = 0;
      continue;
    }
    curpos++;
  }
  if (curpos && buf[curpos - 1] == ‘-‘) flg = -1;
  else flg = 1;
  while (‘0‘ <= buf[curpos] && buf[curpos] <= ‘9‘) {
    ret = ret * 10 + (buf[curpos] - ‘0‘);
    curpos++;
  }
  return ret * flg;
}
int main() {
    n=nxint(),m=nxint();
    register int a,b,c,d;
    rep(i,1,n) val[i]=nxint();
    segtree::maketree(1,n);
    rep(i,1,m){
        a=nxint();b=nxint();c=nxint();d=nxint();
        if(a==1)segtree::update(b,c,d,1,n);
        else {
          segtree::ans.init();
          segtree::query(b,c,1,n);
        write(segtree::ans.query(d));
        putchar(‘\n‘);
    }
}

原文地址:https://www.cnblogs.com/nervendnig/p/10847087.html

时间: 2024-11-14 13:13:32

comet oj #3 D 区间维护异或后的线性基的相关文章

线性空间和异或空间(线性基)bzoj4004贪心+高斯消元

线性空间:是由一组基底构成的所有可以组成的向量空间 对于一个n*m的矩阵,高斯消元后的i个主元可以构成i维的线性空间,i就是矩阵的秩 并且这i个主元线性无关 /* 每个向量有权值,求最小权极大线性无关组 本题是使用贪心策略的高斯消元 由输入给出的n个物品,每个物品有m种属性,和价格price 如果a物品的属性可以由其他已有物品的属性组合出,那么a可以不必购买 问最少花掉多少钱,使得所有物品都可以组合出 首先构建n*m矩阵,然后高斯消元 在求第i个主元时,取价格最小的那个即可 可用反证法证明 */

Comet OJ - Contest #5

Comet OJ - Contest #5 总有一天,我会拿掉给\(dyj\)的小裙子的. A 显然 \(ans = min(cnt_1/3,cnt_4/2,cnt5)\) B 我们可以感性理解一下,最大的满足条件的\(x\)不会太大 因为当\(x\)越来越大时\(f(x)\)的增长速度比\(x\)的增长速度慢得多 其实可以证明,最大的满足的\(x\)不会超过\(100\) 因为没有任何一个三位数的各位之和大于等于\(50\) 所以我们就直接预处理\(1-99\)所有的合法的 暴力枚举即可 其实

CodeForces 587 E.Duff as a Queen 线段树动态维护区间线性基

https://codeforces.com/contest/587/problem/E 一个序列, 1区间异或操作 2查询区间子集异或种类数 题解 解题思路大同小异,都是利用异或的性质进行转化,std和很多网友用的都是差分的思想,用两棵线段树 第一棵维护差分序列上的线性基,第二棵维护原序列的异或区间和,两者同时进行修改 考虑两个序列 $(a,b)(d,e)$,按照std的想法,应该是维护$(0 \^ a,a \^ b)(0 \^ d,d \^ e)$ 然后合并首尾变成$(0 \^ a,a \^

Comet OJ Contest #3

A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 510 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}

Comet OJ - Contest #10 B

Comet OJ - Contest #10 B 沉鱼落雁 思维题 题意 : 每个数字最多重复出现三次,有n给数字,让你尽可能的使得相同数字之间的最小距离尽可能大 思路 :分三种情况套路 设 a b c 分别代表出现 一次, 两次, 三次 数字的个数 所有元素至多出现一次,答案为 n,题目规定 所有元素至多出现两次, 例如 1 1 2,可以排列成 1 2 1,所以,答案为 1 例如 1 1 2 2 3,可以排列成 1 2 3 1 2,所有 答案为 2 思考后得出,应该尽可能的把 b 个出现两次的

线段树 --- (区间维护+逆推)

Buy Tickets Time Limit:4000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue- The Lunar New Year was appro

hdu 1556 Color the ball(线段树区间维护+单点求值)

传送门:Color the ball Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 25511    Accepted Submission(s): 12393 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele

Splay伸展树入门(单点操作,区间维护)

ps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是一颗二叉搜索树,刚刚开始学的时候找题hash数字的题先测板子... 后来那题被学长改了数据不能用平衡树测了...一道二分数字的题. 二叉搜索树的功能是,插入一个数字,在O(logn)的时间内找到它,并操作,插入删除等.但是可能会让二叉搜索树退化成链,复杂度达到O(n) 原文地址:https://www.c

Comet OJ - 2019 六一欢乐赛

传送门 #A: 思路:等差数列求和,看成俩次1+2+…+ n,多加的n减去,所以 ans = n*(n+1) - n. AC代码: 1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 using namespace std; 5 int main() 6 { 7 int n; 8 while(cin >> n) 9 { 10 cout << n*(n+1) - n <