[Ynoi2017]由乃的OJ
题意
由乃正在做她的OJ。现在她在处理OJ上的用户排名问题。OJ上注册了n个用户,编号为1~",一开始他们按照编号
排名。由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号:然而由乃心情非常不好,因为Deus天
天问她题。。。因为Deus天天问由乃OI题,所以由乃去学习了一下OI,由于由乃智商挺高,所以OI学的特别熟练她
在RBOI2016中以第一名的成绩进入省队,参加了NOI2016获得了金牌保送
Deus:这个题怎么做呀?
yuno:这个不是NOI2014的水题吗。。。
Deus:那如果出到树上,多组链询问,带修改呢?
yuno:诶。。。???
Deus:这题叫做睡觉困难综合征哟~
虽然由乃OI很好,但是她基本上不会DS,线段树都只会口胡,比如她NOI2016的分数就是100+100+100+0+100+100。
。。NOIP2017的分数是100+0+100+100+0+100所以她还是只能找你帮她做了。。。
给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示。
每次询问包含三个数x,y,z,初始选定一个数v。然后v依次经过从x到y的所有节点,每经过一个点i,v就变成v opti
xi,所以他想问你,最后到y时,希望得到的值尽可能大,求最大值?给定的初始值v必须是在[0,z]之间。每次修
改包含三个数x,y,z,意思是把x点的操作修改为y,数值改为z

0 <= n , m <= 100000 , k <= 64
分析
参照clover_hxy的题解。
这道题与Noi2014起床困难综合症 十分类似。同样的每一位也是互补影响的,那么最基础的思路就是对于每一位分开维护,对于树进行树链剖分,对于线段树中的区间维护以0,1打头从左到右和从右到左分别计算出的答案。
但是单纯的这么做时间复杂度非常多。所以我们考虑将每一位压到一个unsigned long long 中。对于最底层的节点我们之间计算他的点值和运算符。考虑上面区间的维护,假设左区间以0开头的每一位得到的答案是011,那么如果要合并的答案的话,第一位是0,应该接右区间以0开头该位得到的答案。 以1开头的从左到右为例,那么合并其实就是(l.v1&r.v1)|((~l.v1)&r.v0))
时间复杂度\(O(n + m (\log^2 n + \log v))\)。
代码
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef unsigned long long ULL;
using namespace std;
co ULL mx=0-1;
co int N=2e5;
int opt[N],n,m,k,point[N],nxt[N],v[N],belong[N],son[N];
int fa[N],size[N],pos[N],tot,deep[N],q[N],sz;
ULL val[N],mi[N];
struct data{
ULL v0,v1,w0,w1;
}tr[N*4],ans[N],ans1[N];
void add(int x,int y){
++tot,nxt[tot]=point[x],point[x]=tot,v[tot]=y;
++tot,nxt[tot]=point[y],point[y]=tot,v[tot]=x;
}
void dfs(int x,int f){
size[x]=1,deep[x]=deep[f]+1;
for(int i=point[x];i;i=nxt[i]){
if(v[i]==f) continue;
fa[v[i]]=x;
dfs(v[i],x);
size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]]) son[x]=v[i];
}
}
void dfs1(int x,int chain){
belong[x]=chain,pos[x]=++sz,q[sz]=x;
if(!son[x]) return;
dfs1(son[x],chain);
for(int i=point[x];i;i=nxt[i])
if(v[i]!=son[x]&&v[i]!=fa[x]) dfs1(v[i],v[i]);
}
ULL calc(ULL num,int x){
if(opt[x]==1) return num&val[x];
if(opt[x]==2) return num|val[x];
if(opt[x]==3) return num^val[x];
}
data update(co data&l,co data&r){
data now;
now.v0=(l.v0&r.v1)|(~l.v0&r.v0);
now.v1=(l.v1&r.v1)|(~l.v1&r.v0);
now.w0=(r.w0&l.w1)|(~r.w0&l.w0);
now.w1=(r.w1&l.w1)|(~r.w1&l.w0);
return now;
}
void build(int now,int l,int r){
if(l==r){
int t=q[l];
tr[now].v0=tr[now].w0=calc(0,t);
tr[now].v1=tr[now].w1=calc(mx,t);
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
tr[now]=update(tr[now<<1],tr[now<<1|1]);
}
void pointchange(int now,int l,int r,int x){
if(l==r){
int t=q[l];
tr[now].v0=tr[now].w0=calc(0,t);
tr[now].v1=tr[now].w1=calc(mx,t);
return;
}
int mid=(l+r)>>1;
if(x<=mid) pointchange(now<<1,l,mid,x);
else pointchange(now<<1|1,mid+1,r,x);
tr[now]=update(tr[now<<1],tr[now<<1|1]);
}
data query(int now,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return tr[now];
int mid=(l+r)>>1;
if(qr<=mid) return query(now<<1,l,mid,ql,qr);
if(ql>mid) return query(now<<1|1,mid+1,r,ql,qr);
return update(query(now<<1,l,mid,ql,qr),query(now<<1|1,mid+1,r,ql,qr));
}
data solve(int x,int y){
int cnt=0,cnt1=0;
while(belong[x]!=belong[y]){
if(deep[belong[x]]>deep[belong[y]]){
ans[++cnt]=query(1,1,n,pos[belong[x]],pos[x]);
x=fa[belong[x]];
}
else{
ans1[++cnt1]=query(1,1,n,pos[belong[y]],pos[y]);
y=fa[belong[y]];
}
}
if(deep[x]<deep[y]) ans1[++cnt1]=query(1,1,n,pos[x],pos[y]);
else ans[++cnt]=query(1,1,n,pos[y],pos[x]);
for(int i=1;i<=cnt;++i)
swap(ans[i].v0,ans[i].w0),swap(ans[i].v1,ans[i].w1);
data sum;
if(cnt){
sum=ans[1];
for(int i=2;i<=cnt;++i)
sum=update(sum,ans[i]);
if(cnt1) sum=update(sum,ans1[cnt1]);
}
else sum=ans1[cnt1];
for(int i=cnt1-1;i>=1;--i)
sum=update(sum,ans1[i]);
return sum;
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(m),read(k);
mi[0]=1;
for(int i=1;i<k;++i)
mi[i]=mi[i-1]<<1;
for(int i=1;i<=n;++i)
read(opt[i]),read(val[i]);
for(int i=1;i<n;++i)
add(read<int>(),read<int>());
dfs(1,0),dfs1(1,1);
build(1,1,n);
for(int i=1;i<=m;++i){
int op=read<int>(),x=read<int>(),y=read<int>();
ULL z=read<ULL>();
if(op==2){
opt[x]=y,val[x]=z;
pointchange(1,1,n,pos[x]);
}
else{
data t=solve(x,y);
ULL ans=0;
for(int i=63;i>=0;--i){
ULL t0=t.v0>>i&1,
t1=t.v1>>i&1;
if(t0>=t1||mi[i]>z) ans|=(t0?mi[i]:0);
else ans|=(t1?mi[i]:0),z-=mi[i];
}
printf("%llu\n",ans);
}
}
return 0;
}
[Ynoi2017]由乃的OJ的更多相关文章
- 【BZOJ4811】[Ynoi2017]由乃的OJ 树链剖分+线段树
[BZOJ4811][Ynoi2017]由乃的OJ Description 由乃正在做她的OJ.现在她在处理OJ上的用户排名问题.OJ上注册了n个用户,编号为1-",一开始他们按照编号排名. ...
- 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分+线段树区间合并
题解: 好像和noi那题并没有什么区别 只是加上了修改和变成树上 比较显然我们可以用树链剖分来维护
- BZOJ4811 [Ynoi2017]由乃的OJ 树链剖分
原文链接http://www.cnblogs.com/zhouzhendong/p/8085286.html 题目传送门 - BZOJ4811 题意概括 是BZOJ3668长在树上并加上修改和区间询问 ...
- Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心
传送门 题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值.需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的 ...
- bzoj 4811: [Ynoi2017]由乃的OJ
树链剖分,用zkw线段树维护每条链两个方向上对每一位的变换情况,由于位数较少,可以用两个unsigned long long表示 #include<cstdio> typedef unsi ...
- [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)
起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...
- BZOJ4811 [Ynoi2017]由乃的OJ
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- BZOJ4811 Ynoi2017由乃的OJ(树链剖分+线段树)
先考虑NOI2014的水题,显然从高位到低位贪心,算一下该位取0和1分别得到什么即可. 加强这个水题,变成询问区间.那么线段树维护该位取0和1从左到右和从右到左走完这个节点表示的区间会变成什么即可,也 ...
- 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心
Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...
随机推荐
- PS命令和kill命令
名称:ps使用权限:所有使用者使用方式:ps [options] [--help]说明:显示瞬间行程 (process) 的动态参数:ps的参数非常多, 在此仅列出几个常用的参数并大略介绍含义-A ...
- java查询图片显示无图片显示项目默认图片
/** * 读取图片 * @param request * @param record * @return */ @RequestMapping(params ="method=queryW ...
- linux CentOS7 安装字体库-转
前言 报表中发现有中文乱码和中文字体不整齐(重叠)的情况,首先考虑的就是操作系统是否有中文字体,在CentOS 7中发现输入命令查看字体列表是提示命令无效: 如上图可以看出,不仅没有中文字体,连字体库 ...
- layer.prompt添加多个输入框
原文链接:https://www.jianshu.com/p/65fea33e6750 我们都知道layer.prompt官网上的例子是一个弹出框,那么有没有可能出来多个呢,当然是可以的 1.首先增加 ...
- JVM(三) 对象的创建过程
1.对象的创建过程 1.1 . 给对象分配内存 对象的内存分配有两种方式,一种是指针碰撞另外一种是空闲列表的方式,堆是否规整由我们垃圾回收器来决定的 ,如果垃圾回收带有我们的压缩算法,那么他会规整的分 ...
- 使用qt creator来编译 调试 用CMakeLists组织的工程
爱情原如树叶一样,在人忽视里绿了,在忍耐里露出蓓蕾. -- 何其芳 使用CMake作为构建系统,需要自己写 ...
- dotnet Core学习之旅(一):安装SDK
[重要:文中所有外链不能确保永久有效] >环境 .NET Core 包含两个部分 .NET Core Runtime 和 .NET Core SDK(包含Runtime) 点击此处到达下载页面( ...
- 第1章 云端开发平台Salesforce CRM
1.1云计算平台 传统软件的开发往往耗资成千上万(甚至几百万)美元,有时需要几年的专业服务帮助建立和定制应用程序,而软件的业务问题往往由于其十分复杂或成本太高而无法触及.随着Internet的革新,改 ...
- Linux上安装pstree命令(-bash: pstree: command not found)
一.pstree命令的安装 1.在 Mac OS上 brew install pstree 2.在 Fedora/Red Hat/CentOS yum -y install psmisc 3.在 Ub ...
- Consul 注册中心介绍
在 Spring Cloud 体系中,几乎每个角色都会有两个以上的产品提供选择,比如在注册中心有:Eureka.Consul.zookeeper.etcd 等:网关的产品有 Zuul.Spring C ...