luogu#P9580. 「Cfz Round 1」Wqs Game

    ID: 13549 远端评测题 1200ms 512MiB 尝试: 0 已通过: 0 难度: 6 上传者: 标签>树状数组洛谷原创O2优化线性基洛谷月赛单调栈

「Cfz Round 1」Wqs Game

题目背景

『博』和『奕』喜欢博弈,尤其喜欢 wqs 带权博弈。

题目描述

wqs 带权博弈在一个数列 {ai}\{a_i\} 上进行,对应有一个 0101{bi}\{b_i\}

  1. bi=0b_i=0,则 aia_i 这个数字是属于『博』的;
  2. bi=1b_i=1,则 aia_i 这个数字是属于『奕』的。

游戏规则是,每次给定一个区间 [l,r][l,r],从 ala_lara_r,拥有这个数的人依次决定选该数或者不选,两个人都会采用最优策略

因为『博』很强大,她会让着『奕』,于是博弈的规则是,如果最后两个人选的数按位异或和不为零,则『奕』获胜,否则『博』获胜。

注意每个人能看到对方的选数情况,可以选多个数(只要这个数是自己的),最后计算两个人选数的总异或和。

对于任意区间 [l,r][l,r],若『奕』获胜,则 w(l,r)=1w(l,r)=1,否则 w(l,r)=0w(l,r)=0

每次查询 l=LRr=lRw(l,r)\sum\limits_{l=L}^R\sum\limits_{r=l}^Rw(l,r) 的值,对 2322^{32} 取模。

由于输入输出量过大,对于 tp0tp\ne 0 的测试点,选手需要自行生成数列 aia_i 和询问区间 [L,R][L,R],并用特殊方式输出答案。

注意正解不依赖特殊的输入输出方式。

输入格式

第一行三个正整数 n,q,tpn,q,tp,表示数列长度,天数以及每天局数,以及读入方式。

第二行一个长度为 nn 的字符串,表示 0101{bi}\{b_i\}

tp=0tp=0,则第三行 nn 个正整数,表示数列 {ai}\{a_i\},接下来 qq 行,每行两个正整数 L,RL,R,表示询问 l=LRr=lRw(l,r)\sum\limits_{l=L}^R\sum\limits_{r=l}^Rw(l,r)2322^{32} 取模的值。

否则,令 Sd 初值为 tptpCnt 初值为 00,先使用函数 GetA 依次生成 aia_i,再使用函数 GetLR 依次生成 L,RL,R,具体方式以代码形式后附。

输出格式

tp=0tp=0 则输出 qq 行,每行一个正整数,表示该询问的答案。

否则,令 ansians_i 为第 ii 次询问的答案,你需要输出 (ansi×i)mod232(ans_i\times i)\bmod 2^{32}按位异或和

3 2 0
100
3 1 2
1 3
2 3
2
0
5 2 0
10100
2 7 6 3 5
1 5
2 4
8
4
20 100 8551679995685981130
11001000000000000000
1673

提示

【样例解释 #1】

只有 w(1,1)=w(1,2)=1w(1,1)=w(1,2)=1

对于区间 [1,3][1,3],如果『奕』选第一个数,则『博』选后两个数,否则『博』不选,于是『博』获胜。

注意是从左往右依次选取,『博』在选后两个数之前能够知道『奕』是否选了第一个数。

【样例解释 #2】

只有 $w(1,1)=w(1,2)=w(1,3)=w(1,4)=w(2,3)=w(2,4)=w(3,3)=w(3,4)=1$。

【样例解释 #3】

由于本样例 tp0tp\ne 0,所以你需要使用特殊方式输入输出。

【数据范围】

对于所有数据,$1\le n\le5\times10^5,1\le q\le 1.5\times10^6,0<a_i<2^{60},1\le L\le R\le n,0\le tp<2^{64}$。

子任务编号 分值 nn\le qq\le tptp ai<a_i< 特殊性质
11 66 2020 100100 =0=0 2602^{60}
22 77 100100 10310^3 2102^{10}
33 88 700700
44 99 30003000 10510^5 2602^{60}
55 1414 3×1043\times10^4 2202^{20}
66 1717 2×1052\times10^5 1.5×1061.5\times10^6 1\ge1 2602^{60}
77 1919 5×1055\times10^5
88 2020

特殊性质:序列 bib_i 中最多有 101000

【备注】

数据生成方式:

using ul=unsigned long long;
using ui=unsigned int;
ui Ans,ans;
ul Sd,Cnt;
ul Rd(){Sd^=Sd<<19,Sd^=Sd>>12,Sd^=Sd<<29;return Sd^=++Cnt;}
void GetA(ul &a){a=Rd()%((1ull<<60)-2)+1;}
void GetLR(int &l,int &r){
    l=Rd()%n+1,r=Rd()%n+1;
    if(l>r)swap(l,r);
}
int main(){
    //read n,q,tp,b[i]
    if(tp){
        Sd=tp,Cnt=0;
        for(int i=1;i<=n;++i)GetA(a[i]);
        for(int qi=1;qi<=q;++qi){
            GetLR(l,r);
            //sol
            Ans^=ans*qi;
        }
        printf("%u\n",Ans);
	}
}