Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心
题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值。需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的整数值,在从$x$到$y$的路径上,每走到一个点就与这个点对应的数值进行对应的位运算,求到达$y$点时数字的可能的最大值。$N,\text{操作数} \leq 10^5$,数字在$unsigned long long$范围内。
可以先去做NOI2014的起床困难综合征
考虑用起床困难综合征的贪心策略加上树链剖分解决这道题。首先我们需要解决一个问题:在起床困难综合征中,我们每一次枚举一位,就整个跑一边,看当前位取$1$是否会产生更大的贡献;但是在这一道题中显然是不能每一次都跑一边的。我们需要快速地维护每一位为$0$或$1$时这一位运算之后得到的答案。因为每一位之间是不相互冲突的,所以我们可以将$2^{64}-1$和$0$分别带入求解,这样第$i$位为$1$时的贡献就是带入$2^{64}-1$时第$i$位的值,而第$i$位为$0$时的贡献就是带入$0$时第$i$位的值。
接下来我们考虑如何用线段树维护这两个值。可以知道在合并的时候,当前这个区间带入$2^{64}-1$的值时的答案就是左边一半带入$2^{64}-1$时的答案再带到右边得到的答案,$0$同理。所以也可以用位运算很快的表示出来,不是很有思路的可以去看下面的$merge$
然后我们就可以树链剖分然后跳跳跳了。
注意一个细节:因为链可以不是直上直下的,在往上的过程中$dfs$序是在变小的,而在往下的过程中在变大,所以在线段树中需要同时维护从左往右和从右往左计算的值(也就是下面的$ltor$和$rtol$)。
#include<bits/stdc++.h>
#define ull unsigned long long
#define lch (now << 1)
#define rch (now << 1 | 1)
#define mid ((l + r) >> 1)
//This code is written by Itst
using namespace std;
inline ull read(){
ull a = ;
char c = getchar();
while(c != EOF && !isdigit(c))
c = getchar();
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ ');
c = getchar();
}
return a;
}
;
struct node{
ull ltor[] , rtol[] , val;
int op;
node(){
ltor[] = rtol[] = -;
ltor[] = rtol[] = ;
}
}Tree[MAXN << ];
struct Edge{
int end , upEd;
}Ed[MAXN << ];
int head[MAXN] , ind[MAXN] , rk[MAXN] , dep[MAXN] , top[MAXN] , fa[MAXN] , size[MAXN] , son[MAXN] , op[MAXN];
ull num[MAXN];
int ts , N , M , cntEd , K;
inline ull calc(ull a , ull b , int op){
switch(op){
:
return a & b;
:
return a | b;
:
return a ^ b;
}
}
inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
void dfs1(int x , int f){
fa[x] = f;
dep[x] = dep[f] + ;
size[x] = ;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != f){
dfs1(Ed[i].end , x);
size[x] += size[Ed[i].end];
if(size[son[x]] < size[Ed[i].end])
son[x] = Ed[i].end;
}
}
void dfs2(int x , int t){
top[x] = t;
ind[x] = ++ts;
rk[ts] = x;
if(!son[x])
return;
dfs2(son[x] , t);
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != fa[x] && Ed[i].end != son[x])
dfs2(Ed[i].end , Ed[i].end);
}
inline node merge(node l , node r){
node t;
t.ltor[] = (l.ltor[] & r.ltor[]) | (~l.ltor[] & r.ltor[]);
t.ltor[] = (l.ltor[] & r.ltor[]) | (~l.ltor[] & r.ltor[]);
t.rtol[] = (r.rtol[] & l.rtol[]) | (~r.rtol[] & l.rtol[]);
t.rtol[] = (r.rtol[] & l.rtol[]) | (~r.rtol[] & l.rtol[]);
return t;
}
void init(int now , int l , int r){
if(l == r){
Tree[now].op = op[rk[l]];
Tree[now].val = num[rk[l]];
Tree[now].ltor[] = Tree[now].rtol[] = calc(- , Tree[now].val , Tree[now].op);
Tree[now].ltor[] = Tree[now].rtol[] = calc( , Tree[now].val , Tree[now].op);
}
else{
init(lch , l , mid);
init(rch , mid + , r);
Tree[now] = merge(Tree[lch] , Tree[rch]);
}
}
void modify(int now , int l , int r , int tar){
if(l == r){
Tree[now].op = op[rk[l]];
Tree[now].val = num[rk[l]];
Tree[now].ltor[] = Tree[now].rtol[] = calc(- , Tree[now].val , Tree[now].op);
Tree[now].ltor[] = Tree[now].rtol[] = calc( , Tree[now].val , Tree[now].op);
}
else{
if(mid >= tar)
modify(lch , l , mid , tar);
else
modify(rch , mid + , r , tar);
Tree[now] = merge(Tree[lch] , Tree[rch]);
}
}
node query(int now , int l , int r , int L , int R){
if(l >= L && r <= R)
return Tree[now];
node p;
if(mid >= L)
p = merge(p , query(lch , l , mid , L , R));
if(mid < R)
p = merge(p , query(rch , mid + , r , L , R));
return p;
}
inline void work(int x , int y , ull maxN){
node l , r;
int tx = top[x] , ty = top[y];
while(tx != ty)
if(dep[tx] > dep[ty]){
l = merge(query( , , N , ind[tx] , ind[x]) , l);
x = fa[tx];
tx = top[x];
}
else{
r = merge(query( , , N , ind[ty] , ind[y]) , r);
y = fa[ty];
ty = top[y];
}
if(dep[x] > dep[y])
l = merge(query( , , N , ind[y] , ind[x]) , l);
else
r = merge(query( , , N , ind[x] , ind[y]) , r);
swap(l.rtol[] , l.ltor[]);
swap(l.rtol[] , l.ltor[]);
l = merge(l , r);
ull ans = , now = ;
; i >= ; --i){
ull t = (ull) << i , p = l.ltor[] & t , q = l.ltor[] & t;
if(q >= p || now + t > maxN)
ans += q;
else{
now += t;
ans += p;
}
}
printf("%llu\n" , ans);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("3613.in" , "r" , stdin);
//freopen("3613.out" , "w" , stdout);
#endif
N = read();
M = read();
K = read();
; i <= N ; ++i){
op[i] = read();
num[i] = read();
}
; i < N ; ++i){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
dfs1( , );
dfs2( , );
init( , , N);
int o , x , y;
ull z;
while(M--){
o = read();
x = read();
y = read();
z = read();
)
work(x , y , z);
else{
op[x] = y;
num[x] = z;
modify( , , N , ind[x]);
}
}
;
}
Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心的更多相关文章
- bzoj4811 [Ynoi2017]由乃的OJ 树链剖分+贪心+二进制
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4811 题解 我现在为什么都写一题,调一天啊,马上真的退役不花一分钱了. 考虑这道题的弱化版 N ...
- [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)
起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...
- BZOJ4811 [Ynoi2017]由乃的OJ 树链剖分
原文链接http://www.cnblogs.com/zhouzhendong/p/8085286.html 题目传送门 - BZOJ4811 题意概括 是BZOJ3668长在树上并加上修改和区间询问 ...
- bzoj4811 [Ynoi2017]由乃的OJ 树链剖分+位运算
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4811 因为位运算的结果有可合并性,所以可以树链剖分,线段树维护: 细节很多,特别要注意从左往 ...
- 【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树
[BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...
- 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分+线段树区间合并
题解: 好像和noi那题并没有什么区别 只是加上了修改和变成树上 比较显然我们可以用树链剖分来维护
- 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心
Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...
- Luogu3613 睡觉困难综合征
题面描述https://www.luogu.org/problemnew/show/3613 原题NOI2014起床困难综合症https://www.luogu.org/problemnew/show ...
- 洛谷3613睡觉困难综合征(LCT维护链信息(前后缀)+贪心)
这个题目还是很好啊QWQ很有纪念意义 首先,如果在序列上且是单次询问的话,就是一个非常裸的贪心了QWQ这也是NOI当时原题的问题和数据范围 我们考虑上树的话,应该怎么做? 我的想法是,对于每一位建一个 ...
随机推荐
- 【读书笔记】iOS-Game Kit
名字虽然叫Game Kit,但是Game Kit并不是仅仅开发游戏用的,它为开发者提供了两个非常实用的功能:使用Bonjour通过蓝牙进行点对点的网络传输功能,以及应用内语音聊天功能.有意思的是,语音 ...
- 03--css形状--css揭秘
形状 一 自适应的椭圆 1.难题 1> 圆 你可能注意到过, 给任何正方形元素设置一个足够大的border-radius, 就可以把它变成一个圆形.所用到的CSS 代码如下所示: #bd { w ...
- openCV 色彩空间
---恢复内容开始--- 1.使用cv2.inrange()获取某个范围内的图像取值,指定某个通道的最小值和最大值 import numpy as np def color_space(image): ...
- recovery 升级过程执行自定义shell命令
有时候我们需要,在升级的过程中,执行一些shell命令,来完成我们的一些需求,利用升级过程,进行一些特殊化的操作,思路如下: 第一: 把我们需要执行的命令,写成一个test.sh脚本,然后在recov ...
- HTTP的Referrer和Referrer Policy设置
Referrer referrer是HTTP请求header的报文头,用于指明当前流量的来源参考页面.通过这个信息,我们可以知道访客是怎么来到当前页面的.这对于Web Analytics非常重要,可以 ...
- JMeter—后置处理器(十)
参考<全栈性能测试修炼宝典JMeter实战>第六章 JMeter 元件详解中第五节后置处理器后置处理器是用来处理采样器发送的请求后得到的响应数据 一.Debug PostProcessor ...
- c#所有部门及其下所部门生成树形图(递归算法获取或键值对方式获取)
部门数据库的设计: 代码: /// <summary> /// 获取部门(入口) /// </summary> /// <returns></returns& ...
- Intel P4 CPU
1. P4 CPU 结构 奔4处理器是Intel的经典之作,它是采用乱序执行内核的超标量处理器.P4采用的微架构称为 Net Burst,基本结构如下: 奔4处理器微架构被分成了4大部分: (1)存储 ...
- 开发测试技巧|辅助开发调试:goolge浏览器利用F12在控制台输入脚本实现表单自动填充
一个开发测试技巧的指引和截图,利用google浏览器的F12调试和Console执行,注入JavaScript脚本实现表单的自动填充和测试. 原文链接: http://www.lookdaima.co ...
- Zabbix3.x 监控磁盘IO与自定义模板
引言 Zabbix自带的模板,帮助我们完成了一些比较常用的监控.但如果想要监控磁盘的IO,zabbix并没有给我们提供这么一个模板,所以我们需要自己来创建一个模板来完成磁盘IO的监控. 操作步骤 1. ...