传送门

题意:给出一个$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 树链剖分、贪心的更多相关文章

  1. bzoj4811 [Ynoi2017]由乃的OJ 树链剖分+贪心+二进制

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4811 题解 我现在为什么都写一题,调一天啊,马上真的退役不花一分钱了. 考虑这道题的弱化版 N ...

  2. [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)

    起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...

  3. BZOJ4811 [Ynoi2017]由乃的OJ 树链剖分

    原文链接http://www.cnblogs.com/zhouzhendong/p/8085286.html 题目传送门 - BZOJ4811 题意概括 是BZOJ3668长在树上并加上修改和区间询问 ...

  4. bzoj4811 [Ynoi2017]由乃的OJ 树链剖分+位运算

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4811 因为位运算的结果有可合并性,所以可以树链剖分,线段树维护: 细节很多,特别要注意从左往 ...

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

    [BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...

  6. 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分+线段树区间合并

    题解: 好像和noi那题并没有什么区别 只是加上了修改和变成树上 比较显然我们可以用树链剖分来维护

  7. 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心

    Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...

  8. Luogu3613 睡觉困难综合征

    题面描述https://www.luogu.org/problemnew/show/3613 原题NOI2014起床困难综合症https://www.luogu.org/problemnew/show ...

  9. 洛谷3613睡觉困难综合征(LCT维护链信息(前后缀)+贪心)

    这个题目还是很好啊QWQ很有纪念意义 首先,如果在序列上且是单次询问的话,就是一个非常裸的贪心了QWQ这也是NOI当时原题的问题和数据范围 我们考虑上树的话,应该怎么做? 我的想法是,对于每一位建一个 ...

随机推荐

  1. python之递归与二分法

    1. 递归 自己调用自己 递归的入口(参数) 和 出口(return) 树形结构的遍历 import os def func(lujing, n): lst = os.listdir(lujing) ...

  2. docker第一章:docker核心概念及centos6下安装

    Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...

  3. 每篇半小时1天入门MongoDB——1. MongoDB介绍和安装

    目录:ASP.NET MVC企业级实战目录 MongoDB简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据 ...

  4. QQ浏览器兼容模式问题

    今天客户反馈有个问题,他说用360浏览器的兼容模式无法登陆系统,我试了可以,接着试了IE11,也可以,然后跟经理汇报,他说他用qq浏览器兼容模式就不可以,于是我试了,果然不可以... 问题是酱紫的:输 ...

  5. 你不可不知的Java引用类型之——软引用

    定义 软引用是使用SoftReference创建的引用,强度弱于强引用,被其引用的对象在内存不足的时候会被回收,不会产生内存溢出. 说明 软引用,顾名思义就是比较"软"一点的引用. ...

  6. android recovery代码修改之原生建议

    我们都知道recovery升级的时候,是根据升级脚本updater-script里面的函数,去一步步执行的,比如mount,format等相关的操作,有时候我们需要增加一些自己特殊的更新的接口,这时候 ...

  7. [20170705]理解linux su命令.txt

    [20170705]理解linux su命令.txt --//我一般在维护时经常使用root用户登录,然后su - oracle 转到其他用户操作--//一般都加入 - 参数.这个已经成了条件反射.. ...

  8. Linux文件和目录的粘滞位(sticky bit)

    今天维护系统时发现一个非常诡异的问题:AAA用户和BBB用户同属AAA组,但用AAA用户创建的文件,权限设置为777后,还是不能用BBB用户删除.诡异! 几经周转,发现AAA用户创建文件位置的上层目录 ...

  9. Java概述和项目演示

    Java概述和项目演示 1. 软件开发学习方法 多敲 多思考 解决问题 技术文档阅读(中文,英文) 项目文档 多阅读源码 2. 计算机 简称电脑,执行一系列指令的电子设备 3. 硬件组成 输入设备:键 ...

  10. oracle启动的三个阶段

    startup nomount 时,数据库状态为 started; alter database mount 时, 状态为 mounted; alter database open 时,状态为 ope ...