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-Nib的一些知识
Apple在Xcode4.2中推出用于iOS应用故事版概念. 标识:Identity(标识)检查器最常用于为用户界面元素或者控制器分配一个自定义类. 属性:Attributes(属性)检查器在微调用户 ...
- Android FileUtils 文件操作类
系统路径 Context.getPackageName(); // 用于获取APP的所在包目录 Context.getPackageCodePath(); //来获得当前应用程序对应的apk文件的路径 ...
- 配置Synwrite作为Python的IDE
先建立批处理 建立SynPython.bat ::Synwrite call Python to compile file ::Set Path @ set PATH=H:\XPprogram\Cod ...
- 用Python实现数据结构之队列
队列 队列与栈的类型很相似,但它遵循的原则是先进先出(FIFO),也就是元素插入的时候只能在该数据结构的末端,而删除只能删除最前面的元素.队列同样应用广泛,例如打印机的队列或者是一个web服务器响应请 ...
- Win10更换电脑,又不想重装系统的解决方法
问题描述: 在公司因为两年前用的i3的电脑很卡,然后想换i5的电脑,但是又不想重装系统,因为安装的东西太多了,重装很麻烦 Windows to go介绍: Windows To Go是Windows ...
- Burp Suite 抓取http、https流量配置+CA证书安装
HTTPS协议是为了数据传输安全的需要,在HTTP原有的基础上,加入了安全套接字层SSL协议,通过CA证书来验证服务器的身份,并对通信消息进行加密.基于HTTPS协议这些特性,我们在使用Burp Pr ...
- 百度地图API开发
1.首先申请百度地图秘钥 http://lbsyun.baidu.com/ 2.需要填一个申请的界面 3.申请后会有类似的东西 4.之后参照以下网址进行MFC编译 mfc webbrowser控件使用 ...
- 17秋 软件工程 团队第五次作业 Alpha Scrum7
17秋 软件工程 团队第五次作业 Alpha Scrum7 今日完成的任务 世强:部员详情列表的编写与数据交互,完善APP通知模块: 港晨:完成前端登陆界面编写: 树民:完善Web后端数据库访问模块: ...
- mysqldump与innobackupex备份过程你知多少
mysqldump与innobackupex备份过程你知多少 测试库表创建(这里在同一个库下创建两个表,一个表为innodb引擎,一个为myisam引擎) root@localhost : (none ...
- 环境搭建-----IntelliJ idea之resin配置
目前网上的相关资料太少了 自己只能摸索着尝试 最后在领导的帮忙下 成功实现了环境的集成 网上查到的一般都是修改resin的配置文件等等 其实完全没有必要 本人之前在intellij下部署resin遇到 ...