[BZOJ2908]又是nand

试题描述

首先知道A nand B=not(A and B) (运算操作限制了数位位数为K)比如2 nand 3,K=3,则2 nand 3=not (2 and 3)=not 2=5。

给出一棵树,树上每个点都有点权,定义树上从a到b的费用为0与路径上的点的权值顺次nand的结果,例如:从2号点到5号点顺次经过2->3->5,权值分别为5、7、2,K=3,那么最终结果为0 nand 5 nand 7 nand 2=7 nand 7 nand 2=0 nand 2=7,现在这棵树需要支持以下操作。

①    Replace a b:将点a(1≤a≤N)的权值改为b。

②    Query a b:输出点a到点b的费用。

请众神给出一个程序支持这些操作。

输入

第一行N,M,K,树的节点数量、总操作个数和运算位数。

接下来一行N个数字,依次表示节点i的权值。

接下来N-1行,每行两个数字a,b(1≤a,b≤N)表示a,b间有一条树边。

接下来M行,每行一个操作,为以上2类操作之一。

输出

对于操作②每个输出一行,如题目所述。

输入示例

3 3 3
2 7 3
1 2
2 3
Query 2 3
Replace 1 3
Query 1 1

输出示例

4
7

数据规模及约定

100%的数据N、M≤100000,K≤32

题解

线段树题强行套在树上。。。

注意到 nand 运算没有结合律,所以不能直接维护。进一步分析发现 0 nand x = x nand 0 = 1 (x ∈ {0, 1}),所以我们只用关心一条路径上最后一个 0 的位置,然后数它后面 1 的个数,分奇偶性讨论一下就可以了。注意整条链权值都是 1 的情况特殊处理一下。什么你说我上面只讨论了一位二进制的情况?因为最多不超过 32 位,所以我们建 32 棵线段树就好了。

还有,因为询问有方向,所以线段树需要维护区间中最后一个和最靠前一个 0 的位置。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;
#define LL long long

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
	if(Head == Tail) {
		int l = fread(buffer, 1, BufferSize, stdin);
		Tail = (Head = buffer) + l;
	}
	return *Head++;
}
LL read() {
	LL x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); }
	return x * f;
}

#define maxn 100005
#define maxm 200005
int n, q, k, m, head[maxn], next[maxm], to[maxm];
LL val[maxn];

void AddEdge(int a, int b) {
	to[++m] = b; next[m] = head[a]; head[a] = m;
	swap(a, b);
	to[++m] = b; next[m] = head[a]; head[a] = m;
	return ;
}

int siz[maxn], son[maxn], fa[maxn], dep[maxn], top[maxn], pos[maxn], w, qos[maxn];
void build(int u) {
	siz[u] = 1;
	for(int e = head[u]; e; e = next[e]) if(fa[u] != to[e]) {
		fa[to[e]] = u;
		dep[to[e]] = dep[u] + 1;
		build(to[e]);
		siz[u] += siz[to[e]];
		if(!son[u] || siz[son[u]] < siz[to[e]]) son[u] = to[e];
	}
	return ;
}
void build(int u, int tp) {
	pos[u] = ++w; top[u] = tp; qos[w] = u;
	if(son[u]) build(son[u], tp);
	for(int e = head[u]; e; e = next[e]) if(to[e] != fa[u] && to[e] != son[u])
		build(to[e], to[e]);
	return ;
}

int mx[33][maxn<<2], mn[33][maxn<<2];
LL V[maxn];
void build(int t, int L, int R, int o) {
	if(L == R) {
		int x = V[L] - (V[L] >> (LL)t + 1ll << (LL)t + 1ll) >> (LL)t;
		if(x) mx[t][o] = -1, mn[t][o] = n + 1;
		else mx[t][o] = mn[t][o] = L;
		return ;
	}
	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
	build(t, L, M, lc); build(t, M+1, R, rc);
	mx[t][o] = max(mx[t][lc], mx[t][rc]);
	mn[t][o] = min(mn[t][lc], mn[t][rc]);
	return ;
}
void update(int t, int L, int R, int o, int p) {
	if(L == R) {
		int x = V[L] - (V[L] >> (LL)t + 1ll << (LL)t + 1ll) >> (LL)t;
		if(x) mx[t][o] = -1, mn[t][o] = n + 1;
		else mx[t][o] = mn[t][o] = L;
		return ;
	}
	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
	if(p <= M) update(t, L, M, lc, p);
	else update(t, M+1, R, rc, p);
	mx[t][o] = max(mx[t][lc], mx[t][rc]);
	mn[t][o] = min(mn[t][lc], mn[t][rc]);
	return ;
}
int ql, qr;
int querymx(int t, int L, int R, int o) {
	if(ql <= L && R <= qr) return mx[t][o];
	int M = L + R >> 1, lc = o << 1, rc = lc | 1, ans = -1;
	if(ql <= M) ans = max(ans, querymx(t, L, M, lc));
	if(qr > M) ans = max(ans, querymx(t, M+1, R, rc));
	return ans;
}
int querymn(int t, int L, int R, int o) {
	if(ql <= L && R <= qr) return mn[t][o];
	int M = L + R >> 1, lc = o << 1, rc = lc | 1, ans = n + 1;
	if(ql <= M) ans = min(ans, querymn(t, L, M, lc));
	if(qr > M) ans = min(ans, querymn(t, M+1, R, rc));
	return ans;
}
int lca(int a, int b) {
	int f1 = top[a], f2 = top[b];
//	puts("lcahere");
	while(f1 != f2) {
//		printf("%d %d %d %d\n", a, f1, b, f2);
		if(dep[f1] < dep[f2]) swap(f1, f2), swap(a, b);
		a = fa[f1]; f1 = top[a];
	}
	if(dep[a] > dep[b]) swap(a, b);
	return a;
}
int last[40], last2[40];
LL query(int a, int b) {
	memset(last, -1, sizeof(last));
	memset(last2, -1, sizeof(last2));
	int c = lca(a, b), f1 = top[a], f2 = top[b], A = a, B = b;
//	puts("here");
	while(f1 != top[c]) {
		ql = pos[f1]; qr = pos[a];
		for(int i = 0; i < k; i++) {
			int tmp = querymn(i, 1, n, 1);
			if(tmp <= n) last[i] = qos[tmp];
		}
		a = fa[f1]; f1 = top[a];
	}
	ql = pos[c]; qr = pos[a];
	for(int i = 0; i < k; i++) {
		int tmp = querymn(i, 1, n, 1);
		if(tmp <= n) last[i] = qos[tmp];
	}
	while(f2 != top[c]) {
		ql = pos[f2]; qr = pos[b];
		for(int i = 0; i < k; i++) {
			int tmp = querymx(i, 1, n, 1);
			if(last2[i] < 0 && tmp >= 0) last2[i] = qos[tmp];
		}
		b = fa[f2]; f2 = top[b];
	}
	ql = pos[c]; qr = pos[b];
	for(int i = 0; i < k; i++) {
		int tmp = querymx(i, 1, n, 1);
		if(last2[i] < 0 && tmp >= 0) last2[i] = qos[tmp];
	}

//	for(int i = 0; i < k; i++) printf("%d ", last[i]); putchar(‘\n‘);
//	for(int i = 0; i < k; i++) printf("%d ", last2[i]); putchar(‘\n‘);
	LL ret = 0;
//	printf("lca: %d\n", c);
	for(int i = 0; i < k; i++) {
		int dis;
		if(last[i] < 0 && last2[i] < 0) dis = dep[A] + dep[B] - dep[c] - dep[c];
		else {
			if(last2[i] >= 0) dis = dep[B] - dep[last2[i]];
			else dis = dep[last[i]] + dep[B] - dep[c] - dep[c];
		}
//		printf("%d ", dis);
		ret |= ((((LL)dis & 1ll) ^ 1ll) << (LL)i);
	}
//	putchar(‘\n‘);
	return ret;
}

int main() {
	n = read(); q = read(); k = read();
	for(int i = 1; i <= n; i++) val[i] = read();
	for(int i = 1; i < n; i++) {
		int a = read(), b = read();
		AddEdge(a, b);
	}

	build(1);
	build(1, 1);
	for(int i = 1; i <= n; i++) V[pos[i]] = val[i];
	for(int i = 0; i < k; i++) build(i, 1, n, 1);
	while(q--) {
		char tp = Getchar();
		while(!isalpha(tp)) tp = Getchar();
		LL a = read(), b = read();
		if(tp == ‘Q‘) printf("%lld\n", query(a, b));
		if(tp == ‘R‘) {
			V[pos[a]] = b;
			for(int i = 0; i < k; i++) update(i, 1, n, 1, pos[a]);
		}
	}

	return 0;
}
时间: 2024-10-13 21:46:12

[BZOJ2908]又是nand的相关文章

【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树

[BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名.由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号:然而由乃心情非常不好,因为Deus天天问她题...因为Deus天天问由乃OI题,所以由乃去学习了一下OI,由于由乃智商挺高,所以OI学的特别熟练她在RBOI2016中以第一名的成绩进入省队,参加了NOI2016获得了金牌保送 Deus:这个题怎么做

怎么看时序图--nand flash的读操作详解(转载)

出处:http://blog.chinaunix.net/uid-28852942-id-3992727.html这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的.你需要至少了解 你手上的 nand flash的物理结构和一些诸如读写命令 操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明. 由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈. 这里 我用的 K9F2G08-SCB0 这款nand flas

如何挖掘NAND Flash的IO性能

NAND Flash芯片是构成SSD的基本存储单元,NAND Flash芯片工艺的发展.结构的变化将会推动整个闪存存储产业的高速发展.在设计闪存存储系统的时候,特别是在设计NAND Flash控制器.SSD盘或者卡的时候,都需要深入的了解NAND Flash的操作方法.接口命令及其时序.一个NAND Flash芯片虽然非常小,采用LGA或者TSOP的封装形式,但是,其内部结构还是非常复杂的.特别是随着存储密度的不断提高,NAND Flash内部抽象的概念也越来越多,例如Flash颗粒.Devic

怎么看时序图--nand flash的读操作详解 (转)

这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的.你需要至少了解 你手上的 nand flash的物理结构和一些诸如读写命令 操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明. 由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈. 这里 我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读.不同的芯片操作时序可能不同,读的命令也会有一些差别. 当然其实有时候像nand flash

MTD下的Nand驱动

目录 MTD下的Nand驱动 引入 平台设备资源文件 关键数据结构 平台框架 s3c24xx_nand_probe nand_scan s3c2410_nand_add_partition add_mtd_partitions 字符设备add 块设备add 队列 程序设计 参考 平台设备文件 必备的构造结构 步骤简述 测试 内核配置去除NAND 使用nfs文件系统启动 加载驱动 分区表打印 mtd-utils 复制文件系统回来 完整程序 title: MTD下的Nand驱动 tags: linu

NAND闪存一个月涨价20% SSD硬盘价格全面上涨

闪存跌价已经两年了,但是现在好日子要结束了. 自从 6 月份东芝.西数位于日本的 NAND 闪存工厂断电停工一个月之后,闪存市场就一直有各种涨价的传闻,听多了大家觉得这就是狼来了,实际上并不是,Q3 季度闪存价格就已经开始收窄,这两个月来价格甚至是突变. 从闪存价格来看,11 月底到现在的 12 月底价格涨势最为明显,从闪存市场的报价来看,512Gb TLC 闪存在 11 月底不过 4.10 美元,现在已经达到了 4.32 美元,涨幅大约5%. 5% 听起来不多,但很多产品情况并不一样,部分产品

移植u-boot-2015.10到JZ2440开发板(五)——设置nand分区,环境变量保存地址和其它默认参数

在下载内核或文件系统时,我们可以直接在命令中写明烧到nandflash的具体地址,但较麻烦,我们可以给nandflash分区,这样就可直接写烧到那个分区就行了,较为方便.如何设置呢?首先我们在uboot中输入mtdparts命令,看看默认的分区,结果提示mtdids not defined, no default present.搜索"mtdids not defined",定位到common/cmd_mtdparts.c的mtdparts_init函数中,分析发现是mtdids_de

软件众包是什么?软件外包又是什么?

软件众包?软件外包?这两个之间有关系吗? 随着互联网时代的发展,有着许多的现代新词出现,面对这些新词,刚了解的我也是一脸懵,身处软件开发行业,接触多了也就自己了解了.软件众包,是指一个公司或机构把过去由员工执行的工作任务,以自由自愿的形式外包给非特定的大众网络的做法.简单地来说,就是一个公司有设计.程序员.前端开发等职位,他们平时是互不相关,但公司突然接到一个项目,需要他们在一起合作完成,这就是所谓的软件众包!那软件外包又是什么呢?软件外包又称资源外包,一般认为它是指企业整合利用其外部最优秀的专

NAND flash学习所获----(Zac)

Nand Falsh外围电路:peripheral circuit 1.Nand flash里至少有2个state Machine(controller),即2个主控. 一个主控:负责处理前端事情. 一个主控:负责后端任务处理. 2.DDC:Dynamic Data cache(包括SDC,PDC,TDC,DDC1,DDC2),有的解析为Page buffer,或者sense Amps. 镁光的NAND flash:L94C:单die 8G,L95B:单die 16G 大致的物理结构图: 所以体