小L的占卜
Posted liankewei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小L的占卜相关的知识,希望对你有一定的参考价值。
小L的占卜
题目描述
小 X
的妹妹小 L
是一名 XXX 国的占卜师,她平日的工作就是为 X
国进行占卜。
X
国的占卜殿中有一条长度为 NNN 米的走廊,先人在走廊的每一米都放置了一座神龛,第 iii 座神龛能够产生 AiA_iAi? 点灵力。相同类型的神龛产生的灵力是相同的,不同类型的神龛产生的灵力是不同的,也就是说,如果两座神龛 iii, jjj 产生的灵力 Ai,AjA_i, A_jAi?,Aj? 相同,那么神龛 i,ji, ji,j 是相同类型的神龛,否则,神龛 i,ji, ji,j 是不同类型的神龛。
在占卜时,小 L
首先会指定一个区间 [L,R][L, R][L,R],区间 [L,R][L, R][L,R] 中所有出现过的神龛将参与占卜,若一种类型的神龛出现了奇数次,那么在这次占卜中,该类型的神龛呈阴性,否则在这次占卜中,该类型的神龛呈阳性。然后,小 L
会指定阴性或阳性中的一种属性,区间 [L,R][L, R][L,R] 中这种属性的每一类型的神龛都会有恰好一座产生灵力。
接着,代表光明和黑暗的两大祭司将轮流取走一座还有灵力剩余的神龛中的一部分灵力,取走的灵力点数一定要是整数,取走最后一点灵力的祭司将会代表 X
国一年 的命运。光明祭司和黑暗祭司都是十分聪明的人,因此她们始终会采取尽量让自己取走最后一点灵力的策略。 可以看出,这场占卜的本质是一场 NimNimNim 游戏,最终 X
国一年的命运将会和产生灵力的神龛产生的灵力点数的异或和直接相关,因此,小 L
希望你能够帮她计算出这个异或和。
输入格式
第一行一个整数 NumNumNum,表示测试点编号,以便选手方便地获得部分分,你可能不需要用到这则信息,样例中 NumNumNum 的含义为数据范围与某个测试点相同。
接下来一行两个整数 NNN、MMM,表示占卜走廊的长度,以及小 L
进行的占卜次数。
接下来一行 NNN 个整数 AiA_iAi?,表示第 iii 座神龛能够产生的灵力点数。
接下来 MMM 行,每行 333 个整数 LLL、RRR、TTT,分别表示一次占卜选中的区间和属性,若 T=0T = 0T=0,则表示选中的是阴性,若 T=1T = 1T=1,则表示选中的是阳性。
输出格式
输出 MMM 行,每行一个整数 AnsAnsAns,表示产生灵力的神龛产生的灵力点数的异或和。
样例
样例输入
2
7 5
1 2 1 3 3 2 3
4 6 0
4 5 1
1 3 1
1 7 0
1 5 1
样例输出
2
3
1
3
2
样例解释
在第一次占卜中,区间 [4,6][4, 6][4,6] 中的神龛分布为 [3,3,2][3, 3, 2][3,3,2],其中呈阴性的神龛类型为2{2}2,它们产生的灵力点数异或和为 222。
在第二次占卜中,区间 [4,5][4, 5][4,5] 中的神龛分布为 [3,3][3, 3][3,3],其中呈阳性的神龛类型为 3{3}3,它们产生的灵力点数异或和为 333。
在第三次占卜中,区间 [1,3][1, 3][1,3] 中的神龛分布为 [1,2,1][1, 2, 1][1,2,1],其中呈阳性的神龛类型为1{1}1,它们产生的灵力点数异或和为 111。
在第四次占卜中,区间 [1,7][1, 7][1,7] 中的神龛分布为 [1,2,1,3,3,2,3][1, 2, 1, 3, 3, 2, 3][1,2,1,3,3,2,3],其中呈阴性的神龛类型为 {3},它们产生的灵力点数异或和为 3。
在第五次占卜中,区间 [1,5][1, 5][1,5] 中的神龛分布为 [1,2,1,3,3][1, 2, 1, 3, 3][1,2,1,3,3],其中呈阳性的神龛类型为 1,3{1,3}1,3,它们产生的灵力点数异或和为 222。
数据范围与提示
对于所有测试数据,保证 1≤L≤R≤N≤106,0≤M≤106,T∈0,1,0≤Ai<2301 ≤ L ≤ R ≤ N ≤ 10^6,0 ≤ M ≤ 106,T ∈ {0, 1},0 ≤ Ai < 2^301≤L≤R≤N≤106,0≤M≤106,T∈0,1,0≤Ai<230。 详细的数据范围见下表。
solution
80pts 莫队
100pts
对于奇数的询问,直接输出异或和就行。
考虑比较麻烦的偶数。
把询问离线,按右端点排序。
对于一个右端点,某个数值v的贡献是一段一段的,即00000vvvvv00000vvvv这样
如果这时候加入一个v,那么上一次的v往前所有有贡献的都会取反,即有变成没,没变成有
由于异或两次等于没有,我们直接区间异或就行。
树状数组可以实现。
效率O(nlog^2)
而树状数组和map的常数都不大,可以过。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<map> 8 #define maxn 1000006 9 using namespace std; 10 int n,m,a[maxn],ax[maxn],ans[maxn]; 11 int tr[maxn]; 12 map<int,int>ls; 13 struct node{ 14 int l,r,t,id; 15 }q[maxn]; 16 bool cmp(node a,node b){ 17 return a.r<b.r; 18 } 19 void add(int i,int v){ 20 for(;i<=n;i+=i&-i)tr[i]^=v; 21 } 22 int ask(int i){ 23 int sum=0; 24 for(;i;i-=i&-i)sum^=tr[i]; 25 return sum; 26 } 27 int R(){ 28 int v=0;char ch; 29 while(!isdigit(ch=getchar()));v=ch-48; 30 while(isdigit(ch=getchar()))v=v*10+ch-48; 31 return v; 32 } 33 int main() 34 { 35 n=R();n=R();m=R(); 36 for(int i=1;i<=n;i++){ 37 a[i]=R(); 38 ax[i]=ax[i-1]^a[i]; 39 } 40 for(int i=1;i<=m;i++){ 41 q[i].id=i; 42 q[i].l=R();q[i].r=R();q[i].t=R(); 43 } 44 sort(q+1,q+m+1,cmp); 45 int now=1; 46 for(int i=1;i<=m;i++){ 47 for(;now<=q[i].r;now++){ 48 int la=ls[a[now]]; 49 add(1,a[now]);add(la+1,a[now]); 50 //cout<<la<<‘ ‘<<a[now]<<endl; 51 ls[a[now]]=now; 52 } 53 if(q[i].t==0) ans[q[i].id]=ax[q[i].r]^ax[q[i].l-1]; 54 else ans[q[i].id]=ask(q[i].l); 55 } 56 for(int i=1;i<=m;i++)printf("%d ",ans[i]); 57 return 0; 58 }
以上是关于小L的占卜的主要内容,如果未能解决你的问题,请参考以下文章