传送门

题意:给出一个$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. CSS--理解块级格式上下文(BFC)

    1.BFC 定义 BFC(Block formatting context)直译为"块级格式化上下文".它是一个独立的渲染区域,只有Block-level box(块级元素)参与, ...

  2. Javascript异步编程之三Promise: 像堆积木一样组织你的异步流程

    这篇有点长,不过干货挺多,既分析promise的原理,也包含一些最佳实践,亮点在最后:) 还记得上一节讲回调函数的时候,第一件事就提到了异步函数不能用return返回值,其原因就是在return语句执 ...

  3. 安卓开发_浅谈DatePicker(日期选择器)

    DatePicker继承自FrameLayout类,日期选择控件的主要功能是向用户提供包含年.月.日的日期数据并允许用户对其修改.如果要捕获用户修改日期选择控件中的数据事件,需要为DatePicker ...

  4. 开始记录 Windows Phone 生涯

    已经快接近三年没有更新博客了,最近打算把博客这块从新建设起来. 由于工作原因,现在已经很久没有接触过Android了.目前工作是全力 Windows Phone,并且也已经工作一年半了,以后会陆续把之 ...

  5. 基于bootstrap的双日历插件 daterangepicker

    我遇到需求是要求我将daterangepicker的一个双日期选择格式修改成两个单日期格式的日期选择框(方便手机端显示),要求如下: 1.两个单日期格式分别为开始日期和结束日期 2.开始日期可选择范围 ...

  6. puppeteer入门

    转自: https://www.jianshu.com/p/a89d8d6c007b 作者: ppCode puppeteer新手入门(chromium下载跳坑) ppCode 关注 2017.12. ...

  7. 精通initramfs构建step by step

    (一)hello world  一.initramfs是什么  在2.6版本的linux内核中,都包含一个压缩过的cpio格式 的打包文件.当内核启动时,会从这个打包文件中导出文件到内核的rootfs ...

  8. python中strip()方法学习笔记

    Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 当使用strip('xxx'),只要字符串头尾有"xxx"中的一个,就会去掉,而不是符合字符串''x ...

  9. vs2012\2013\2015 添加 ActiveX制作控件插件 Visual Studio Installer

    由于vs2012.2013 之后的版本升级,之前用vs2010 开发制作的ActvieX控件在高版本12.13上不兼容,需要安装插件支持: 如果是vs2013版本,可参照以下方式下载后安装,若是其他版 ...

  10. 两个列表lst1和lst2,计算两个列表的公共元素和非公共元素

    方法1: 列表推导式 lst1 = [1, 3, 7] lst2 = [3, 5, 4] a = [x for x in lst1 if x in lst2] b = [y for y in (lst ...