20170908 校内模拟赛 游戏

T1.游戏(game)
小 z 和小 Z 最近迷上了玩 Nim 游戏,这个游戏的规则是这样的:有 n 堆石
子,第 i 堆有 ai 个石子。两个人轮流操作,每次可以任意取一堆的任意多个石
子,可以取完或者不取完,谁先取不了谁输。
每次创造一个初始局面过于麻烦, 他们决定把石子聚成很多堆, 又把这些堆
摆成一棵树,每次选择一条链上的所有石子堆作为初始局面玩游戏。当然,他们
还经常修改石子堆里的石子数量。
小 Z 明白这个游戏是有必胜策略的,所以他总是按照策略行动,并且经常
获胜。小 z 并不知道获胜策略,所以他去请教了机智的小 d。在明白了获胜策略
之后他恍然大悟, 这时他回想起了和小 Z 玩的好多场游戏, 他想知道其中有哪些
游戏他一定会失败?
由于小 Z 好强,所以小 z 总是后手。

#include<cstdio>
struct edge{
    int to,nx;
}e[5000001];
int h[500001];
int n,Q,p;
int num;
int a[500001];
int fa[500001][21],dep[500001],l[500001],r[500001];
int BIT[500001];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘0‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
void update(int x,int v){
    for(int i=x;i<=n;i+=(i&(-i))){
        BIT[i]^=v;
    }
}
int query(int x){
    int ans=0;
    for(int i=x;i;i-=(i&(-i))){
        ans^=BIT[i];
    }
    return ans;
}
void ae(int fr,int to){
    e[++p]=(edge){to,h[fr]};h[fr]=p;
}
void dfs(int x){
    for(int i=1;i<=20;i++){
        if(dep[x]>=(1<<i)){
            fa[x][i]=fa[fa[x][i-1]][i-1];
        }
        else break;
    }
    l[x]=++num;
    for(int i=h[x];i;i=e[i].nx){
        int v=e[i].to;
        if(v!=fa[x][0]){
            dep[v]=dep[x]+1;
            fa[v][0]=x;
            dfs(v);
        }
    }
    r[x]=num;
}
int lca(int x,int y){
    if(dep[x]<dep[y]){
        int tm=x;x=y;y=tm;
    }
    int t=dep[x]-dep[y];
    for(int i=0;i<=20;i++){
        if((1<<i)&t) x=fa[x][i];
    }
    for(int i=20;i>=0;i--){
        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    }
    if(x==y) return x;
    return fa[x][0];
}
int main(){
    //freopen("game.in","r",stdin);
    //freopen("game.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    for(int i=1;i<n;i++){
        int x=read(),y=read();
        ae(x,y);ae(y,x);
    }
    dfs(1);
    for(int i=1;i<=n;i++){
        update(l[i],a[i]);update(r[i]+1,a[i]);
    }
    Q=read();
    while(Q--){
        char op[5];
        scanf("%s",op);
        int x=read(),y=read();
        if(op[0]==‘Q‘){
            int LCA=lca(x,y);
            int sg=query(l[x])^query(l[y])^a[LCA];
            if(sg) puts("Yes");
            else puts("No");
        }
        else{
            update(l[x],a[x]);update(r[x]+1,a[x]);
            a[x]=y;
            update(l[x],y);update(r[x]+1,y);
        }
    }
    return 0;
}
时间: 2024-10-11 06:35:13

20170908 校内模拟赛 游戏的相关文章

2017.6.11 校内模拟赛

题面及数据及std(有本人的也有原来的) :2017.6.11 校内模拟赛 T1 自己在纸上模拟一下后就会发现 可以用栈来搞一搞事情 受了上次zsq 讲的双栈排序的启发.. 具体就是将原盘子大小copy一下排个序 用两个指针维护两个数组(原数据 和 排序后的数据), 即分为1数据和2数组 将小于1指针指向的数据的2数组中的数据全部压入栈中 后进行消除, 将栈栈顶元素与当前1数组中的1指针指向的元素进行比较 相同则消除 后重复过程 直至指针超过N 后判断一下是否两个指针都超过了N... #incl

校内模拟赛 Zbq&#39;s Music Challenge

Zbq's Music Challenge 题意: 一个长度为n的序列,每个位置可能是1或者0,1的概率是$p_i$.对于一个序列$S$,它的得分是 $$BasicScore=A\times \sum_{i=1}^{n}{S_i} \tag{1}$$ $$ combo(i)=\left\{ \begin{aligned} &S_i & &i=1 \\ &combo(i-1)+1 & &i\neq 1 ~\mathrm{and}~ S_i=1 \\ &

[20180816]校内模拟赛

T1 清理(clear) 问题描述 小 C 最近自己开发了一款云盘软件,目前已有??个用户.小C 的云盘上的文件会被后台分成两种类型,活动 文件和非活动文件,活动文件即可能常用的文件,会被放在高速服务器上给用户提供高速下载服务.用户 上传一个文件时,这个文件会被设置为活动文件.由于高速服务器内存大小有限,小 C 需要把一些文件 设为非活动文件,有以下两种设置方式:1.把上传时间前??早的文件全部设为非活动文件:2.把第??个用户上 传的文件全部设为非活动文件.注意这两种方式操作的对象都是所有文件

[20180815]校内模拟赛

T1 游戏(game) 问题描述 Alice准备和Bob玩一个游戏,他们先拿出若干堆石子,每一堆里面都有一定数量的石子. Alice和Bob轮流操作,Alice先手,每次操作需要选择一堆石子数量大等于2的石子,把这堆石子分成两堆. 假设这堆石子中有x个石子,那么可以分成一堆y(1≤y<x)个石子和一堆x-y个石子. 如果轮到一个人操作时没有可选的石子堆,这个人就输了. Alice有n堆石子,其中第i堆有\(a_i\)个石子,他打算选出其中连续一段石子跟Bob玩. 你需要回答m次询问,每次查询取出

校内模拟赛T1大美江湖

这就是一个模拟题,注意1234分别对应左右上下横坐标和纵坐标的判断就好了 题解: 需要注意的是,向上取整ceil函数是对于一个double值返回一个double值,也就是说在ceil里面的类型一定要是double,否则会炸 代码: #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #include<string>

校内模拟赛:确定小组

  [问题描述] 有n个人坐成一排,这n个人都在某一个小组中,同一个小组的所有人所坐的位置一定是连续的. 有一个记者在现场进行采访,他每次采访都会询问一个人其所在的小组有多少人,被询问的每个人都给出了正确的答案,但是由于时间仓促,记者不一定询问了每个人,我们记录一个长度为n的答案序列,序列的第i个数表示第i个人的回答,如果为0则表示记者没有询问过这个人. 记者发现,对于一些情况,他可以唯一确定这排所有人的分组,而对于另外一些情况则不能,于是记者开始好奇,对于某一个答案序列,他能不能做到这一点,如

校内模拟赛20170604

香蕉锤--双向链表 #include<iostream> #include<cstdio> using namespace std; inline int read(){ int num=0,t=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} ret

5.13 校内模拟赛

... 果然是dalao们做难题做多了后 简单题水不起来了吗.. 5.13解题报告 300分 T1写了差不多30~40分钟 T2写了不到5min (当时怀疑有坑..) T3推了大概1个多小时的式子, 然后又加上调试差不多一个半小时 时间分配就这样..感觉T2出的太过简单了..直接是个模板 T1 并查集 + 乱搞 T2 快速幂模板 T3 Dp T1 : codevs 2796 最小完全图 二次联通门 : codevs 2796 最小完全图 /* codevs 2796 最小完全图 并查集 + 乱搞

校内模拟赛(20170924)

四校很丧,但是学长的题目更简单 lrb学长的题目为什么都要倒着切,不懂QAQ ----------------我是分割线---------------- T1:个人卫生综合征 每天BBS都要从家里经过城市中的一段路到学校刷五三.城市中一共有n个路口和m条双向道路,每条双向道路都连接着两个路口ai.bi且有一定的时间花费vi.BBS家编号为1,学校编号为n.今天,BBS由于个人卫生综合征导致他很迟才离开家,他想用膜法改变k条道路的长度使通过其的时间花费vi变为0.现在他问你改变道路长度之后他到学校