首页 > 其他分享 >洛谷P5556 圣剑护符

洛谷P5556 圣剑护符

时间:2023-09-09 12:12:12浏览次数:39  
标签:P5556 洛谷 fa 护符 tp son int BIT id

题目链接

先考虑如何判定一个集合是否存在两个异或和相同的子集 \(s,t\),不然解决这道题就是无稽之谈。

根据异或的优良性质,不妨在 \(s,t\) 中分别去掉 \(s\cap t\),之后从 \(s\) 中任意移动 \(|s|-1\) 个元素到 \(t\) 中去,易发现此时两个集合的元素异或和还是相同。也就是说,我们现在只需要逐个判断当前元素能否被其他元素异或出来即可。

于是我们构造一个线性基,逐个插入元素,插入的时候判断一下:如果插入不成功,则说明当前元素可以被异或出来,输出 YES

但在给出的集合数以及集合大小都为 \(10^5\) 的情况下该如何处理?我们再尝试寻找一些性质:根据线性基的大小不超过 \(\log V\),不难得出我们插入成功也必定不超过 \(\log V\) 次。也就是说,如果集合大小 \(>\log V\),直接输出 YES 即可。

再回到原问题。这是一个树上带修问题——使用树链剖分解决即可。树剖中可以不写线段树,只需要写一个区改单查的树状数组。代码细节不多,较为好写。

点击查看代码
#include <bits/stdc++.h>
#define FL(i, a, b) for(int i = (a); i <= (b); i++)
#define FR(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 1e5 + 10, W = 29;
namespace T{
	int n, tot, d[N], fa[N], sz[N], tp[N], son[N], id[N];
	vector<int> e[N];
	namespace BIT{
		int c[N];
		void Add(int x, int v){
			for(; x <= n; x += x & -x) c[x] ^= v;
		}
		int Ask(int x, int r = 0){
			for(; x; x -= x & -x) r ^= c[x]; return r;
		}
	}
	void Dfs1(int u){
		d[u] = d[fa[u]] + (sz[u] = 1);
		for(const int &v: e[u]) if(v != fa[u]){
			fa[v] = u, Dfs1(v), sz[u] += sz[v];
			if(sz[v] > sz[son[u]]) son[u] = v;
		}
	}
	void Dfs2(int u){
		id[u] = ++tot, tp[u] = (son[fa[u]] == u? tp[fa[u]] : u);
		if(son[u]) Dfs2(son[u]);
		for(const int &v: e[u])
			if(v != fa[u] && v != son[u])
				Dfs2(v);
	}
	int Lca(int x, int y){
		while(tp[x] != tp[y]){
			if(d[tp[x]] < d[tp[y]]) swap(x, y);
			x = fa[tp[x]];
		}
		return d[x] < d[y]? x : y;
	}
	void Upd(int x, int y, int z){
		while(tp[x] != tp[y]){
			if(d[tp[x]] < d[tp[y]]) swap(x, y);
			BIT::Add(id[tp[x]], z);
			BIT::Add(id[x] + 1, z), x = fa[tp[x]];
		}
		if(d[x] < d[y]) swap(x, y);
		BIT::Add(id[y], z), BIT::Add(id[x] + 1, z);
	}
	int Qry(int x){return BIT::Ask(id[x]);}
}
using namespace T;
struct LinearBasis{
	int a[W + 2];
	void init(){fill(a, a + W + 1, 0);}
	int insert(int x){
		FR(i, W, 0) if((x >> i) & 1){
			if(!a[i]){a[i] = x; return 1;}
			else x ^= a[i];
		}
		return 0;
	}
} b;
int q, a[N];
int main(){
	scanf("%d%d", &n, &q);
	char op[10]; int x, y, z, lca, u, flag;
	FL(i, 1, n) scanf("%d", &a[i]);
	FL(i, 2, n){
		scanf("%d%d", &x, &y);
		e[x].emplace_back(y), e[y].emplace_back(x);
	}
	Dfs1(1), Dfs2(1); FL(i, 1, n) Upd(i, i, a[i]);
	while(q--){
		scanf("%s%d%d", op, &x, &y);
		if(op[0] == 'U') scanf("%d", &z), Upd(x, y, z);
		else{
			lca = Lca(x, y), b.init();
			flag = (d[x] + d[y] - d[lca] - d[fa[lca]] <= 30);
			for(u = x; flag && u != lca; u = fa[u])
				if(!b.insert(Qry(u))) flag = 0;
			for(u = y; flag && u != fa[lca]; u = fa[u])
				if(!b.insert(Qry(u))) flag = 0;
			printf(flag? "NO\n" : "YES\n");
		}
	}
	return 0;
}

标签:P5556,洛谷,fa,护符,tp,son,int,BIT,id
From: https://www.cnblogs.com/zac2010/p/17689221.html

相关文章

  • 洛谷100题计划(20/100)
    洛谷100题计划(20/100)P1147连续自然数和-洛谷|计算机科学教育新生态(luogu.com.cn)题意就是找一段连续的区间,使得区间和为\(M\),很容易发现,其实这个区间就是一个等差数列,所以\(区间和=\frac{(首项+末项)\times项数}{2}\),假设首项为\(L\),末项为\(R\),那么可以得出......
  • 洛谷P3808 【模板】AC 自动机(简单版)题解 AC自动机模板题
    题目链接:https://www.luogu.com.cn/problem/P3808AC自动机模板题。示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e6+5;structNode{intson[26],fail,id;Node(){}Node(int_id){memset(son,0,sizeof(son));......
  • 洛谷梗大全(5)
    引:洛谷梗大全(1)洛谷梗大全(2)洛谷梗大全(3)洛谷梗大全(4)\[\begin{aligned}&(−1)−1\times(4−5\times1^4)&=&0&&|&&1+1\times(45+1+4)&=&51&\\&1^{(1−4−5^{14})}&=&1&&|&&1-1\times(4-51-4)&......
  • 洛谷梗大全(4)
    \[\Large\boxed{今日运势}\]\[\Large\bold{\color{#8E44AD}Lovely\_Chtholly\\color{black}的运势}\]\[\Huge\color{#E74C3C}\textbf{§}\bold{\吉你钛镁\}\textbf{§}\]\[\scriptsize\text{你已经在洛谷连续打卡了}\normalsize\infty\scriptsize\text{......
  • 洛谷P1228 地毯填补问题
    1#include<bits/stdc++.h>2usingnamespacestd;3intk,x,y;45intjudge(intx,inty,intgx,intgy,intlen)//判断障碍物在哪个区块6{7if(gx<=x+len/2-1&&gy<=y+len/2-1)8return1;9else......
  • 洛谷 P3373 总结
    洛谷P3373题意给定长度为\(n\)的整数序列,有以下三种操作共\(q\)次:将区间\([l,r]\)每一个数乘上\(k\);将区间\([l,r]\)每一个数加上\(k\);求出区间\([l,r]\)的区间和对\(m\)取模后的结果。\(1\leqslantn,q\leqslant10^5\)。思路这个题非常明确......
  • 洛谷p1824 进击的奶牛
    P1824进击的奶牛题目描述FarmerJohn建造了一个有N(2<=N<=100,000)个隔间的牛棚,这些隔间分布在一条直线上,坐标是x1,...,xN(0<=xi<=1,000,000,000)。他的C(2<=C<=N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,FarmerJohn想把这些......
  • 洛谷P1013 [NOIP1998 提高组] 进制位
    P1013[NOIP1998提高组]进制位P1013题目传送门这是一道提高+/省选-的蓝题,有亿点点难度,我们先分析一下。分析字母的数量等于进制的大小,判错的时候,可以看一下那个表格右下角的一个等腰三角形,就会发现有一个由两位字母组成的三角形。我们验算一下,对于\(L\),在该三角形的双位字......
  • 洛谷P5865 [SEERC2018] Tree
    P5865[SEERC2018]Tree题目传送门分析本题不难,只要枚举即可。假设两点之间的距离为树的端点,然后再去枚举其他点,符合的加入集合。若黑色点的个数超出了定义个数,那么就更新一遍。最后求最小值。ACCode:#include<bits/stdc++.h>//保命万能头usingnamespacestd;//命名空......
  • 【LGR-156-Div.3】洛谷网校 8 月普及组月赛 I & MXOI Round 1 & 飞熊杯 #2(同步赛)
    【LGR-156-Div.3】洛谷网校8月普及组月赛I&MXOIRound1&飞熊杯#2(同步赛)\(T1\)luoguP9581宝箱\(100pts\)水题,模拟即可。intmain(){ inta,b,ans=0; cin>>a>>b; if((a<0&&b<0)||(a>0&&b>0)) { cout<<max(abs(a),abs......