首页 > 其他分享 >SPOJ COT3 - Combat on a tree

SPOJ COT3 - Combat on a tree

时间:2024-08-07 18:28:32浏览次数:8  
标签:CI ch return COT3 int tree SPOJ full now

挺好的一个题,算是博弈和 DS 的有机结合

这类问题一眼考虑 SG 函数,同时树上的 SG 函数一般都是从子树向上递推

考虑若某个点的子树内全是黑点,则其 SG 函数为零;否则考虑枚举所有的后继状态

不难发现选中一个白点会把这个子树断成一个森林,这个后继状态的 SG 函数就是每个连通块 SG 函数的异或值

因此可以想要用某种数据结构维护在每个子树内删去一个白点得到的后继状态的 SG 函数值

需要支持的操作有:合并(用来将子树信息向上传递);修改(合并多个子树时需要整体异或某个值);查询 mex

用 0/1Trie 即可实现上述所有功能,其中修改可以用类似线段树懒标记的方法,查询 mex 时只需要维护每个子树是否是满二叉树,类似线段树上二分地递归查询即可

总复杂度 \(O(n\log n)\)

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,c[N],sg[N],rt[N],x,y; vector <int> v[N],ans;
class Trie
{
    private:
        int ch[N*20][2],full[N*20],tag[N*20],idx;
        inline void pushup(CI now)
        {
            full[now]=full[ch[now][0]]&full[ch[now][1]];
        }
        inline void pushdown(CI now,CI k)
        {
            if (tag[now]) update(ch[now][0],tag[now],k-1),update(ch[now][1],tag[now],k-1),tag[now]=0;
        }
    public:
        inline void insert(int& now,CI x,CI k=19)
        {
            if (!now) now=++idx;
            if (k==-1) return (void)(full[now]=1);
            pushdown(now,k);
            insert(ch[now][(x>>k)&1],x,k-1);
            pushup(now);
        }
        inline void update(CI now,CI mv,CI k=19)
        {
            if (!now||k==-1) return;
            if ((mv>>k)&1) swap(ch[now][0],ch[now][1]);
            tag[now]^=mv;
        }
        inline int merge(CI x,CI y,CI k=19)
        {
            if (!x||!y) return x|y;
            if (k==-1) return full[x]|=full[y],x;
            pushdown(x,k); pushdown(y,k);
            ch[x][0]=merge(ch[x][0],ch[y][0],k-1);
            ch[x][1]=merge(ch[x][1],ch[y][1],k-1);
            pushup(x); return x;
        }
        inline int getmex(CI now,CI k=19)
        {
            if (!now||k==-1) return 0;
            pushdown(now,k);
            if (full[ch[now][0]]) return (1<<k)|getmex(ch[now][1],k-1);
            return getmex(ch[now][0],k-1);
        }
}T;
inline void DFS1(CI now=1,CI fa=0)
{
    int ret=0; for (auto to:v[now])
    if (to!=fa) DFS1(to,now),ret^=sg[to];
    for (auto to:v[now]) if (to!=fa)
    T.update(rt[to],ret^sg[to]),rt[now]=T.merge(rt[now],rt[to]);
    if (!c[now]) T.insert(rt[now],ret);
    sg[now]=T.getmex(rt[now]);
    //printf("sg[%d] = %d\n",now,sg[now]);
}
inline void DFS2(CI now=1,CI fa=0,CI pre=0)
{
    int ret=0; for (auto to:v[now]) if (to!=fa) ret^=sg[to];
    if ((ret^pre)==0&&!c[now]) ans.push_back(now);
    for (auto to:v[now]) if (to!=fa) DFS2(to,now,pre^(ret^sg[to]));
}
int main()
{
    scanf("%d",&n); for (RI i=1;i<=n;++i) scanf("%d",&c[i]);
    for (RI i=1;i<n;++i) scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
    if (DFS1(),sg[1]==0) return puts("-1"),0;
    DFS2(); sort(ans.begin(),ans.end());
    for (auto x:ans) printf("%d\n",x);
    return 0;
}

标签:CI,ch,return,COT3,int,tree,SPOJ,full,now
From: https://www.cnblogs.com/cjjsb/p/18347617

相关文章

  • QStyledItemDelegate 和QTreeView实现鼠标hover消息
    1.QTreeView设置属性mousetracking和tablettracing 重写QStyledItemDelegate类,重写函数booleditorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index);这个函数里可以处理鼠标hover和点击事件;boolTreeTas......
  • CF29D Ant on the Tree
    AntontheTree题面翻译无环连通无向图称为树。树是一类图,不仅对于人很有趣,而且对蚂蚁也很有趣。蚂蚁站在树根处。他发现树中有N个顶点,它们由n-1条边连接,因此在任何一对节点之间都有一条路径。叶节点与根节点不同,它只与另一个节点相连。蚂蚁想要访问树中的每个节点并返回到根......
  • Java集合:Collection and Map;ArrayList;LinkList;HashSet;TreeSet;HashMap;TreeMap;Iterator:
        集合介绍:                        是一组变量类型(容器),跟数组很像。一,引用集合的原因(必要性):                  A:数组的空间长度固定,一旦确定不可以更改。多了浪费,少了报错。          B:使用数......
  • 论文解读:LSM Tree 的魔力,提升写入吞吐量的高效数据存储结构
    LSMTree是一种用于高写入吞吐量的数据库存储引擎,广泛应用于现代分布式数据库系统。其核心思想是将写入操作缓存在内存中,并定期批量写入磁盘,减少磁盘I/O操作,提高写入性能。因其高效的写入性能和适应大规模数据的能力,成为现代数据密集型应用的关键技术之一。LSM-tree主要由三......
  • 使用django-treebeard实现树类型存储与编辑
    前言其实之前做很多项目都有遇到跟树相关的功能,以前都是自己实现的,然后前端很多UI组件库都有Tree组件,套上去就可以用。不过既然用Django了,还是得充分发挥一下生态的优势,但是我找了半天,也就这个treebeard能用,其他要不停更了要不就功能很拉,没有可视化编辑树的功能。难道Djang......
  • Luogu P10842 Piggy and Trees 题解 [ 绿 ] [ 拆边 ] [ 贡献思维 ]
    PiggyandTrees:把路径拆成边的思维题。思路一看到这题的路径,就想到了LuoguP3177树上染色这题化路径为边的贡献,分别计算的思维。那么对于此题,先来观察题目里式子的意思:对于树上的每个无序点对,求出树上每个点到这些点对之间的最短路径的距离之和。枚举点对对应的就是前两......
  • 树(tree) - 题解(带权并查集)
    树(tree)时间限制:C/C++2000MS,其他语言4000MS内存限制:C/C++256MB,其他语言512MB描述给定一个\(n\)个结点,\(n−1\)条边的有根树。第\(i\)条边可以用(\(a_i,b_i\))来描述,它表示连接结点\(a_i\)和结点\(b_i\)的一条边,其中结点\(a_i\)是结点\(b_i\)的父节点。......
  • [AGC023F] 01 on Tree
    题意给定一棵\(n\)个节点的树,每个点都有权值\(0/1\),每次删除一个没有父亲的节点,并将权值放在序列末尾。求该序列最小的逆序对数。Sol删除不好做,只能\(\text{dp}\)。考虑把删除改成合并,每次合并\(x\)和\(fa_x\)表示将\(x\)紧接在\(fa_x\)后面。这样维护\(n\)个......
  • SP3912 MTREECOL - Color a tree
    前言NOIP模拟考到了这题,整场比赛死磕这题,最后悲痛拿下\(\text{0+30+0+0=30pts}\)的高分。Solution题意很清楚。每一次染色操作当且仅当父亲节点染过色。每一个节点贡献的价值是点权乘上时间。求贡献和最小。设当前权值最大的节点为\(x\),那么如果\(x\)之前的节点......
  • [学习笔记]最小割树 (Gomory-Hu Tree)
    本文是在作者阅读多篇博客后糅合而成的,部分内容有雷同。最小割树又称Gomory-Hu树,由RalphEdwardGomory和TeChiangHu于1961年发表的论文中共同提出。最小割树可以在\(n−1\)次最大流中构建,并通过树上RMQ求任意两点之间的最小割。板子题:P4897【模板】最小割树(G......