• vijos2001 xor-sigma


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

    描述

    对于给定的n和m以及a1,...,ana1,...,an,请你计算:

     s=ni=1max1jmin{m,ni+1}{aiai+1...ai+j1} }

    s=∑i=1nmax1≤j≤min{m,n−i+1}{ai⊕ai+1⊕...⊕ai+j−1} 

    格式

    输入格式

    第1行为空格分隔的n和m。

    第2行为空格分隔的$${a1,...,ana1,...,an}$$

    输出格式

    一个数字,为计算结果s(只保留低31位即可)。

    样例1

    样例输入1[复制]

     
    10 5
    1 2 3 4 5 6 7 8 9 10

    样例输出1[复制]

     
    92

    限制

    1mn5×1051≤m≤n≤5×105

    i[1,n],1ai2311∀i∈[1,n],1≤ai≤231−1

    时间

    前三个测试点 1s

    剩下的 2s

    空间

    384MiB

    正解:trie+贪心

    解题报告:

      异或类的题目,显然拆成一位一位的会好做多了。记得以前我出的题目里面出过一道类似的...

      按每一位是1或0建一棵trie树,然后因为每次的查询有范围限制,所以可以看做是在trie上动态插入元素或者删除元素,只需要维护一个每个结点的经过次数,就可以处理这个问题。

      插入就很简单了。查询呢?对于sum[i-1](sum数组为前缀异或和)在trie上查询,每一位尽可能选择不同,如果不存在不同的就只能选择这一位选择相同,那么就没有贡献。如果可以不同就继续顺着trie树上走,并加入贡献。

      插入和删除的话就把经过的结点经过次数++或者--。

     1 //It is made by ljh2000
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 using namespace std;
    14 typedef long long LL;
    15 const int inf = (1<<30);
    16 const int MAXN = 10000011;
    17 int n,m,a[MAXN],sum[MAXN];
    18 int tr[MAXN][2],ci[MAXN],cnt;
    19 LL ans;
    20 
    21 inline int getint()
    22 {
    23     int w=0,q=0; char c=getchar();
    24     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
    25     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
    26 }
    27 inline void insert(int x){ 
    28     int u=1,num; ci[u]++;
    29     for(int i=30;i>=0;i--) { 
    30     num=(x>>i)&1; if(!tr[u][num]) tr[u][num]=++cnt;
    31     u=tr[u][num]; ci[u]++;
    32     }
    33 }
    34 inline void del(int x){  int u=1,num; ci[u]--;  for(int i=30;i>=0;i--) { num=(x>>i)&1; u=tr[u][num]; ci[u]--; } }
    35 inline void query(int x){
    36     int u=1,num; int now_ans=0;
    37     for(int i=30;i>=0;i--) {
    38     num=(x>>i)&1; 
    39     if(!tr[u][num^1] || ci[tr[u][num^1]]==0) u=tr[u][num]; 
    40     else u=tr[u][num^1],now_ans+=(1<<i);
    41     }
    42     ans+=now_ans;
    43 }
    44 
    45 inline void work(){
    46     n=getint(); m=getint(); for(int i=1;i<=n;i++) a[i]=getint(),sum[i]=sum[i-1]^a[i]; cnt=1;
    47     int nowl=1; while(nowl<m) insert(sum[nowl]),nowl++;
    48     for(int i=1;i<=n;i++) {
    49     if(nowl<=n) insert(sum[nowl]),nowl++;    
    50     query(sum[i-1]);
    51     del(sum[i]);
    52     }
    53     LL MOD=(1LL<<31); ans%=MOD;
    54     printf("%lld",ans);
    55 }
    56 
    57 int main()
    58 {
    59     work();
    60     return 0;
    61 }
  • 相关阅读:
    validform使用
    kindeditor使用
    初探uni-app
    【心有猛虎】react-lesson
    【心有猛虎】react-pxq
    【水滴石穿】douban-movies-react-native
    【水滴石穿】MyFirstRNDemo
    【水滴石穿】github_popular
    笔记本CPU的型号和类型的区分方法
    List<T>的IndexOf方法和Remove方法
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6028612.html
Copyright © 2020-2023  润新知