本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

题目链接:BZOJ4811

正解:树链剖分+线段树

解题报告:

  因为位与位之间互相独立,考虑直观做法,对于每一位维护两个变量,分别表示这一位输入$0$、$1$之后会变成的值。

  这个复杂度是$O(knlog^2n)$,显然不能通过。

  但是我们不难发现,对于不同的位,其$0$、$1$的变化趋势相同,那么可以用位运算优化, 把每个输入$0$、$1$压成两个二进制数,每次的变化可以变成位运算。

  仔细考虑一下含义,不妨设为$x$、$y$两个变量合并。

  那么$x$的$0$最终会变成的值,应该是$0$变成$1$再从$1$变成$0$,或上$0$保持$0$的情况。想想就能推出来了==

  注意合并顺序。

//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
#define lc root<<1
#define rc root<<1|1
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define reg(i,x) for(int i=first[x];i;i=nxt[i])
using namespace std;
typedef unsigned long long LL;
const int MAXN = 200011;
const int MAXM = 400011;
int n,m,Type[MAXN],ecnt,first[MAXN],nxt[MAXM],to[MAXM],son[MAXN],size[MAXN],top[MAXN],dfn[MAXN],pre[MAXN],deep[MAXN],ql,qr,father[MAXN];
LL chu[MAXN],k,A,mi[100];
bool ok;
struct node{ LL ans0,ans1; }a[MAXN*3],b[MAXN*3],ans,ansx,ansy,tmp;
inline void link(int x,int y){ nxt[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
inline node merge(node q,node qq){ return (node){(q.ans0&qq.ans1) | (~q.ans0&qq.ans0) , (q.ans1&qq.ans1) | (~q.ans1&qq.ans0)}; }
inline LL getint(){
LL w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline node get(int tt,LL z){
if(tt==1) return (node){ 0,(~0)&z };
else if(tt==2) return (node){ z,(~0)|z };
else return (node){ z,(~0)^z };
} inline void dfs(int x,int fa){
size[x]=1;
reg(i,x) {
int v=to[i]; if(v==fa) continue;
deep[v]=deep[x]+1; father[v]=x; dfs(v,x);
size[x]+=size[v]; if(size[v]>size[son[x]]) son[x]=v;
}
} inline void dfs2(int x,int fa){
dfn[x]=++ecnt; pre[ecnt]=x; if(son[x]) top[son[x]]=top[x],dfs2(son[x],x);
reg(i,x) {
int v=to[i]; if(v==fa || v==son[x]) continue;
top[v]=v; dfs2(v,x);
}
} inline void build(int root,int l,int r){
if(l==r) {
int x=pre[l];
a[root]=b[root]=get(Type[x],chu[x]);
return ;
}
int mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1,r);
a[root]=merge(a[lc],a[rc]);
b[root]=merge(b[rc],b[lc]);
} inline void modify(int root,int l,int r,int pos,int tt,LL z){
if(l==r) {
a[root]=get(tt,z);
b[root]=get(tt,z);
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) modify(lc,l,mid,pos,tt,z);
else modify(rc,mid+1,r,pos,tt,z);
a[root]=merge(a[lc],a[rc]);
b[root]=merge(b[rc],b[lc]);
} inline void query(int root,int l,int r,int type){
if(ql<=l && r<=qr) {
if(!ok) {
ok=true;
tmp=type?a[root]:b[root];
}
else {
if(type) tmp=merge(tmp,a[root]);
else tmp=merge(tmp,b[root]);
}
return ;
}
int mid=(l+r)>>1;
if(qr<=mid) query(lc,l,mid,type);
else if(ql>mid) query(rc,mid+1,r,type);
else {
if(type) query(lc,l,mid,type),query(rc,mid+1,r,type);//down y!!!
else query(rc,mid+1,r,type),query(lc,l,mid,type);//up x!!!
}
} inline void lca(int x,int y){
int f1=top[x],f2=top[y];
bool flag1=false,flag2=false;
while(f1!=f2) {
if(deep[f1]<deep[f2]) {
ql=dfn[f2]; qr=dfn[y]; ok=false;
query(1,1,n,1);
y=father[f2]; f2=top[y];
if(!flag2) ansy=tmp,flag2=true;
else ansy=merge(tmp,ansy);
}
else {
ql=dfn[f1]; qr=dfn[x]; ok=false;
query(1,1,n,0);
x=father[f1]; f1=top[x];
if(!flag1) ansx=tmp,flag1=true;
else ansx=merge(ansx,tmp);
}
}
if(deep[x]<deep[y]) {
ql=dfn[x]; qr=dfn[y]; ok=false;
query(1,1,n,1);
if(!flag2) ansy=tmp,flag2=true;//!!!
else ansy=merge(tmp,ansy);
}
else {
ql=dfn[y]; qr=dfn[x]; ok=false;
query(1,1,n,0);
if(!flag1) ansx=tmp,flag1=true;//!!!
else ansx=merge(ansx,tmp);
}
if(!flag1) ans=ansy;
else if(!flag2) ans=ansx;
else ans=merge(ansx,ansy);
} inline void work(){
n=getint(); m=getint(); k=getint(); for(int i=1;i<=n;i++) Type[i]=getint(),chu[i]=getint();
int type,x,y; LL z,now; for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); }
deep[1]=1; dfs(1,0);
ecnt=0; dfs2(1,0);
build(1,1,n);
mi[0]=1; for(int i=1;i<=64;i++) mi[i]=mi[i-1]*2;
while(m--) {
type=getint();
if(type==1) {
x=getint(); y=getint(); z=getint();
lca(x,y);
A=0; now=0;
for(long long i=k;i>=0;i--) {
if((ans.ans0>>i)&1) A+=mi[i];
else if(( ans.ans1>>i &1 ) && (now+mi[i]<=z)){
A+=mi[i];
now+=mi[i];
}
}
//cout<<A<<endl;
printf("%llu\n",A);
}
else {
x=getint(); y=getint(); z=getint();
modify(1,1,n,dfn[x],y,z);
}
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("4811.in","r",stdin);
freopen("4811.out","w",stdout);
#endif
work();
return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

  

BZOJ4811 [Ynoi2017]由乃的OJ的更多相关文章

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

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

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

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

  3. BZOJ4811 Ynoi2017由乃的OJ(树链剖分+线段树)

    先考虑NOI2014的水题,显然从高位到低位贪心,算一下该位取0和1分别得到什么即可. 加强这个水题,变成询问区间.那么线段树维护该位取0和1从左到右和从右到左走完这个节点表示的区间会变成什么即可,也 ...

  4. Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心

    传送门 题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值.需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【BZOJ4429】[Nwerc2015] Elementary Math小学数学 最大流

    [BZOJ4429][Nwerc2015] Elementary Math小学数学 Description Ellen给她的学生教小学数学.期末考试已经来临了.考试有n个题目,每一个题目学生们都要对一 ...

  2. 在CentOS中使用 yum 安装MongoDB及服务器端配置

    转自 http://blog.csdn.net/zhangfeng19880710/article/details/20166853 一.准备工作: 运行yum命令查看MongoDB的包信息 [roo ...

  3. SSH电力项目四-显示首页

    1.登录页面: 将上一节中的页面放到/WEB-INF/page/目录下,需要登录后才能访问该页面: 对应页面:/WEB-INF/page/menu/home.jsp <%@ page langu ...

  4. 最短路和次短路的条数(dijstra算法或spfa算法)POJ3463

    http://poj.org/problem?id=3463 Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissio ...

  5. MP3 ID3信息编辑器(附源码)

    练习WPF时写的编辑MP3 ID3信息的小工具,方便对歌曲的统一管理,同时增加了调用豆瓣音乐API获取专辑信息的功能:1.主界面: 2.没有ID3 信息的MP3歌曲: 3.点击自动获取,从豆瓣音乐获取 ...

  6. sosi-statistics

    set echo offset scan onset lines 150set pages 66set verify offset feedback offset termout offcolumn ...

  7. nginx:正向代理和反向代理

    一.正向代理 原理:正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器).为了从目标服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转交并且将获得 ...

  8. nodejs中使用linq

    官网地址 https://github.com/mihaifm/linq 安装 npm install linq 导入 var Enumerable = require(‘linq‘); 例子 1 总 ...

  9. html基础之css标签

    css style: 里面的写的就叫做css,每一个样式的间隔用英文分号, 全部相同的时候引用class. css有三种写法: 1.在head标签中增加style标签,在style标签中去写css样式 ...

  10. 鸟哥linux私房菜学习笔记,U盘安装centos5.3不能正常进入图形界面的问题

    前面说过自己成功引导了centos系统,现在进入启动界面,首次进入会进行相关设置,按照步骤一步一步完成,取消完光盘安装,点击下一步,就进入下面这个界面,没有登录框...没错!怎么蓝屏了,这可是linu ...