【JSOI冬令营2019 A组, Day1T1】小 L 的占卜

时间:2019-02-11
本文章向大家介绍【JSOI冬令营2019 A组, Day1T1】小 L 的占卜,主要包括【JSOI冬令营2019 A组, Day1T1】小 L 的占卜使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目背景

\text{What’s that stir, so blatant in our sallying hearts?}What’s that stir, so blatant in our sallying hearts?

\text{What’s that urge, that lifted up our longing eyes?}What’s that urge, that lifted up our longing eyes?

\text{What’s that ring, echoing from the leaden skies?}What’s that ring, echoing from the leaden skies?

\text{What’s that augur, resounding from the lyre‘s string?}What’s that augur, resounding from the lyre‘s string?

题目描述

小 X 的妹妹小 L 是一名 X 国的占卜师,她平日的工作就是为 X 国进行占卜。

X 国的占卜殿中有一条长度为 NN米的走廊,先人在走廊的每一米都放置了一座神龛,第 ii 座神龛能够产生 A_iAi​ 点灵力。相同类型的神龛产生的灵力是相同的,不同类型的神龛产生的灵力是不同的,也就是说,如果两座神龛 i, ji,j产生的灵力 A_i, A_jAi​,Aj​ 相同,那么神龛 i, j是相同类型的神龛,否则,神龛 i, j是不同类型的神龛。

在占卜时,小 L 首先会指定一个区间 [L, R],区间 [L, R]中所有出现过的神龛将参与占卜,若一种类型的神龛出现了奇数次,那么在这次占卜中,该类型的神龛呈阴性,否则在这次占卜中,该类型的神龛呈阳性。然后,小 L 会指定阴性或阳性中的一种属性,区间 [L, R]中这种属性的每一类型的神龛都会有恰好一座产生灵力。接着,代表光明和黑暗的两大祭司将轮流取走一座还有灵力剩余的神龛中的一部分灵力,取走的灵力点数一定要是整数,取走最后一点灵力的祭司将会代表 X 国一年的命运。光明祭司和黑暗祭司都是十分聪明的人,因此她们始终会采取尽量让自己取走最后一点灵力的策略。

可以看出,这场占卜的本质是一场 Nim 游戏,最终 X 国一年的命运将会和产生灵力的神龛产生的灵力点数的异或和直接相关,因此,小 L 希望你能够帮她计算出这个异或和。

输入输出格式

输入格式:

第一行一个整数 Num,表示测试点编号,以便选手方便地获得部分分,你可能不需要用到这则信息,样例中 NumNum 的含义为数据范围与某个测试点相同。

接下来一行两个整数 N、M,表示占卜走廊的长度,以及小 L 进行的占卜次数。

接下来一行 NN个整数 Ai​,表示第 ii 座神龛能够产生的灵力点数。

接下来 M 行,每行 3 个整数 L、R、T,分别表示一次占卜选中的区间和属性,若 T = 0,则表示选中的是阴性,若 T = 1,则表示选中的是阳性。

输出格式:

输出 MM 行,每行一个整数 AnsAns,表示产生灵力的神龛产生的灵力点数的异或和。

输入输出样例

输入样例#1:

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

输出样例#1: 

2
3
1
3
2

说明

在第一次占卜中,区间 [4, 6] 中的神龛分布为 [3, 3, 2],其中呈阴性的神龛类型为{2},它们产生的灵力点数异或和为 2。

在第二次占卜中,区间 [4, 5] 中的神龛分布为 [3, 3],其中呈阳性的神龛类型为 {3},它们产生的灵力点数异或和为 3。

在第三次占卜中,区间 [1, 3] 中的神龛分布为 [1, 2, 1],其中呈阳性的神龛类型为{1},它们产生的灵力点数异或和为 1。

在第四次占卜中,区间 [1, 7] 中的神龛分布为 [1, 2, 1, 3, 3, 2, 3],其中呈阴性的神龛类型为 {3},它们产生的灵力点数异或和为 3。

在第五次占卜中,区间 [1, 5] 中的神龛分布为 [1, 2, 1, 3, 3],其中呈阳性的神龛类型为 {1,3},它们产生的灵力点数异或和为 2。

数据规模

对于5%的数据,M = 0

对于115%的数据,N \le 10, M \le 10, A_i \le 10

对于30%的数据,N \le 10^3, M \le 10^3

对于80%的数据,N \le 5 \times 10^4, M \le 5 \times 10^4

  • 其中有20\%的数据满足:对于任意 Ai​,存在非负整数 xx 使得 A_i = 2^x

  • 另外,各有10\%的数据满足:T = 0 或 T = 1

对于100\%的数据,N \le 10^6, M \le 10^6, A_i \le 2^{30}, T \in {0, 1}

 

Code:

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define rep2(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
template<typename T> void read(T &num){
    char c=getchar();num=0;T f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();}
    num*=f;
}
template<typename T> void qwq(T x){
    if(x>9)qwq(x/10);
    putchar(x%10+'0');
}
template<typename T> void write(T x){
    if(x<0){x=-x;putchar('-');}
    qwq(x);putchar('\n');
}
int num,n,m;
struct wzy{
    int ll,rr,pos;
}qj[1000010];
map<int,int>last;
int co[1000010];int pre[1000010];int ans[1000010];
int nxt[1000010];bool flag[1000010];
inline bool cmp(wzy a,wzy b){
    return a.ll<b.ll;
}

int tree[1000010];
inline int lowbit(int x){return x&(-x);}
inline void change(int x,int y){
    while(x<=n){tree[x]^=y;x+=lowbit(x);}
    return;
}
inline int query(int x){
    int ans=0;
    while(x){ans^=tree[x];x-=lowbit(x);}
    return ans;
}

int main(){
    read(num);read(n);read(m);
    rep(i,1,n){read(co[i]);pre[i]=(pre[i-1]^co[i]);}
    
    int len=0;
    rep(i,1,m){
        int l,r,t;read(l);read(r);read(t);
        if(!t){ans[i]=(pre[r]^pre[l-1]);}
        else{qj[++len].ll=l;qj[len].rr=r;qj[len].pos=i;}
    }
    sort(qj+1,qj+len+1,cmp);
    rep2(i,n,1){nxt[i]=last[co[i]];last[co[i]]=i;flag[nxt[i]]=1;}
    rep(i,1,n){if(!flag[i]){change(i,co[i]);}}
    
    int pos=0;qj[len+1].ll=INT_MAX;
    rep(i,1,n){
        while(i>qj[pos].ll){pos++;}
        while(i==qj[pos].ll){ans[qj[pos].pos]=((pre[qj[pos].rr]^pre[i-1])^query(qj[pos].rr));pos++;}
        change(i,co[i]);if(nxt[i]){change(nxt[i],co[i]);}
        if(pos==len+1)break;
    }
    
    rep(i,1,m){write(ans[i]);}
    return 0;
}