[Luogu 3613] 睡觉困难综合征
Description
给定一棵 \(n\) 个点的树,每个点上有位运算 \(opt\) 和一个权值 \(x\),位运算有 &,|,^ 三种。
要求支持:
- 修改点 \(v\) 的 \(opt\) 和 \(x_v\)
- 确定一个初始点权在 \([0,z]\) 之间的 \(v_0\),然后依次经过从 \(x\) 到 \(y\) 的所有节点。每经过一个节点 \(i\), \(v\) 就变成 \(v\;opt\;x_i\) 请回答最后到 \(y\) 时可能的最大的 \(v\) 。
Solution
首先五十分的做法比较显然,就是拆位建 \(lct\),然后每位分开做,复杂度 \(O(nk\log n)\)。
这样只有 \(50\) 分,考虑优化复杂度。
因为 \(O(n\log n)\) 已经是 \(lct\) 的复杂度了不是很能优化掉,考虑去掉复杂度乘上的 \(k\)。
有这个 \(k\) 的原因是我们对于每一位都搞了棵 \(lct\) 出来。如果我们只弄一棵 \(lct\) 是否可行呢?
定义 \(f0,f1\) 分别为初始值全 \(0/1\) 走过一条路径之后的答案
那在 \(lct\) 中需要维护的就是 \(splay\) 里 \(x\) 的子树,中序遍历的 \(f0,f1\) 已经倒着的中序遍历(与中序遍历相反)\(f0,f1\) (要维护这个倒着的原因是当前点 \(x\) 的值与左右子树的顺序有关,而 \(splay\) 中又有 \(reverse\) 操作所以要维护)。
那有了这个能不能快速更新呢?也就是说有左区间的 \(f0,f1\) 和右区间的 \(g0,g1\),能不能快速求出来 \(h0,h1\) 呢?废话
更新式子比较显然就是:\(h0=(f0\&g1)+(\sim f0\& g0),h1=(f1\And g1)+(\sim f1\& g0)\)
证明的话就是全 \(0\) 放进去左区间之后跑出来的是 \(f0\),可能长 \(10010001010\) 这样,然后再去 $\And $ 一下 \(g1\) 就代表这些当前为 \(1\) 的位放进右区间之后跑出来的是多少。因为 \(\&\) 了 \(f0\) 所以最后答案肯定不会比 \(f0\) 大。其它几项的证明也类似就不去证了。
最后求出来 从 \(x\) 到 \(y\) 的 \(f0,f1\) 之后贪心的选就好了。
Code
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cctype>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef unsigned long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define all(A) A.begin(),A.end()
#define mp(A,B) std::make_pair(A,B)
namespace NewweN{
const int N=1e5+5;
int n,m,cnt,head[N],stk[N],top;
int fa[N],ch[N][2],tag[N],k;ll maxn;
char buf[1048578];int ptr,MX;
#define ls ch[x][0]
#define rs ch[x][1]
struct Edge{
int to,nxt;
}edge[N<<1];
void add(int x,int y){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
head[x]=cnt;
}
struct Node{
ll a,b;
Node(){}
Node(ll x,ll y){
a=x,b=y;
}
friend Node operator+(Node x,Node y){
return Node((x.a&y.b)+(((~x.a))&y.a),(x.b&y.b)+(((~x.b))&y.a));
}
}l[N],r[N],val[N];
char nc(){
if(ptr==MX) MX=fread(buf,1,1<<20,stdin),ptr=0;
return ptr==MX?EOF:buf[ptr++];
}
#define getchar nc
ll getint(){
ll X=0,w=0;char ch=getchar();
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
}
void dfs(int now,int f=0){
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(to==f)continue;
fa[to]=now;
dfs(to,now);
}
}
void pushup(int x){
l[x]=r[x]=val[x];
if(ls)l[x]=l[ls]+l[x],r[x]=r[x]+r[ls];
if(rs)l[x]=l[x]+l[rs],r[x]=r[rs]+r[x];
}
void pushr(int x){
tag[x]^=1;swap(ls,rs);swap(l[x],r[x]);
}
void pushdown(int x){
if(tag[x])tag[x]=0,pushr(ls),pushr(rs);
}
bool nroot(int x){
return ch[fa[x]][0]==x or ch[fa[x]][1]==x;
}
void rotate(int x){
int y=fa[x],z=fa[y],d=ch[y][1]==x,dd=ch[z][1]==y;
ch[y][d]=ch[x][d^1];if(ch[x][d^1])fa[ch[x][d^1]]=y;
fa[x]=z;if(nroot(y))ch[z][dd]=x;
fa[y]=x;ch[x][d^1]=y;pushup(y);
}
void splay(int x){
int now=x;stk[++top]=now;
while(nroot(now))now=fa[now],stk[++top]=now;
while(top)pushdown(stk[top--]);
while(nroot(x)){
int y=fa[x],z=fa[y];
if(nroot(y))rotate((ch[y][1]==x)^(ch[z][1]==y)?x:y);
rotate(x);
}pushup(x);
}
void access(int x){
for(int y=0;x;y=x,x=fa[x]){
splay(x);rs=y;
pushup(x);
}
}
void makeroot(int x){
access(x),splay(x),pushr(x);
}
void split(int x,int y){
makeroot(x),access(y),splay(y);
}
signed main(){
n=getint(),m=getint(),k=getint();
maxn=(1ull<<k)-1;
for(int i=1;i<=n;i++){
ll x=getint(),y=getint();
if(x==1)val[i]=Node(0,y);
if(x==2)val[i]=Node(y,~0);
if(x==3)val[i]=Node(y,(~y));
}
for(int i=1;i<n;i++){
int x=getint(),y=getint();
add(x,y),add(y,x);
} dfs(1);
while(m--){
int opt=getint(),x=getint(),y=getint();ll z=getint();
if(opt==1){
split(x,y);
ll ans=0,used=0;
for(int i=k-1;~i;i--){
if(l[y].a>>i&1ull) ans|=1ull<<i;
else if((l[y].b>>i&1ull) and (used|(1ull<<i))<=z) ans|=1ull<<i,used|=1ull<<i;
} printf("%llu\n",ans);
} else{
splay(x);
if(y==1) val[x]=Node(0,z);
if(y==2) val[x]=Node(z,~0);
if(y==3) val[x]=Node(z,(~z));
pushup(x);
}
} return 0;
}
}
int yzh=NewweN::main();
signed main(){return 0;}
[Luogu 3613] 睡觉困难综合征的更多相关文章
- 洛谷3613睡觉困难综合征(LCT维护链信息(前后缀)+贪心)
这个题目还是很好啊QWQ很有纪念意义 首先,如果在序列上且是单次询问的话,就是一个非常裸的贪心了QWQ这也是NOI当时原题的问题和数据范围 我们考虑上树的话,应该怎么做? 我的想法是,对于每一位建一个 ...
- Luogu 睡觉困难综合征 ([NOI2014]起床困难综合症)
一.[NOI2014]起床困难综合症 题目描述 网址:https://daniu.luogu.org/problemnew/show/2114 大意: 有一条链,链上每一个节点包含一个位运算f 与 一 ...
- 【刷题】洛谷 P3613 睡觉困难综合征
题目背景 刚立完Flag我就挂了WC和THUWC... 时间限制0.5s,空间限制128MB 因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了 由于二周目 ...
- 省队集训Day1 睡觉困难综合征
传送门:https://www.luogu.org/problem/show?pid=3613 [题解] 按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做. 写棵LCT,维护正反两种权值, ...
- Luogu3613 睡觉困难综合征/BZOJ4811 Ynoi2017 由乃的OJ 树链剖分、贪心
传送门 题意:给出一个$N$个点的树,树上每个点有一个位运算符号和一个数值.需要支持以下操作:修改一个点的位运算符号和数值,或者给出两个点$x,y$并给出一个上界$a$,可以选取一个$[0,a]$内的 ...
- 洛谷P3613 睡觉困难综合征(LCT,贪心)
洛谷题目传送门 膜拜神犇出题人管理员!!膜拜yler和ZSY!! 没错yler连续教我这个蒟蒻写起床困难综合症和睡觉困难综合症%%%Orz,所以按位贪心的思路可以继承下来 这里最好还是写树剖吧,不过我 ...
- 洛谷P3613 睡觉困难综合征(LCT)
题目: P3613 睡觉困难综合症 解题思路: LCT,主要是维护链上的多位贪心答案,推个公式:分类讨论入0/1的情况,合并就好了(公式是合并用的) 代码(我不知道之前那个为啥一直wa,改成结构体就好 ...
- Luogu3613 睡觉困难综合征
题面描述https://www.luogu.org/problemnew/show/3613 原题NOI2014起床困难综合症https://www.luogu.org/problemnew/show ...
- [bzoj3668][Noi2014]起床困难综合症/[洛谷3613]睡觉困难综合症
来自FallDream的博客,未经允许,请勿转载,谢谢. 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm 一直坚持与起床困难综 ...
随机推荐
- python3 安装 opencv (转)
Python3支持pip方式自动安装第三方开发包,我们只要打开windows下面的命令行工具,输入如下命令: pip install opencv-python 安装最新的OpenCV3.3开发包 p ...
- 2019.03.01 bzoj3075: [Usaco2013]Necklace(kmp+dp)
传送门 题意简述:给出S,TS,TS,T两个字串,∣S∣≤10000,∣T∣≤1000|S|\le10000,|T|\le1000∣S∣≤10000,∣T∣≤1000,问至少从SSS中删去几个字符能够 ...
- CQOI2018 简要题解
破解D-H协议 列个式子会发现是BSGSBSGSBSGS的模板题,直接码就是了. 代码: #include<bits/stdc++.h> #include<tr1/unordered ...
- 2019.02.21 bzoj5317: [Jsoi2018]部落战争(凸包+Minkowski和)
传送门 题意:qqq次询问把一个凸包整体加一个向量(x,y)(x,y)(x,y)之后是否与另外一个凸包相交. 思路:转化一下发现只要会求A+B={v⃗=a⃗+b⃗∣a⃗∈A,b⃗∈B}A+B=\{\v ...
- Codeforces Round #546 (Div. 2) E 推公式 + 线段树
https://codeforces.com/contest/1136/problem/E 题意 给你一个有n个数字的a数组,一个有n-1个数字的k数组,两种操作: 1.将a[i]+x,假如a[i]+ ...
- Linux运维40道精华题
题目 1.什么是运维?什么是游戏运维? 1)运维是指大型组织已经建立好的网络软硬件的维护,就是要保证业务的上线与运作的正常,在他运转的过程中,对他进行维护,他集合了网络.系统.数据库.开发.安全.监控 ...
- pyhon_day1 格式化输出
格式化输出 我们在写Python的在很多时候输出的内容需要规定格式的,这样就引入到了格式化输出 定义: 盗用下大咖的例子: ------------ info of alex ----------- ...
- PostgreSQL和MySQL
PostgreSQL分布式
- 内置函数_zip()
zip() zip()函数用来把多个可迭代对象中的元素压缩到一起,返回一个可迭代的zip对象,其中每个元素都是包含原来的多个可迭代对象对应位置上元素的元组,最终结果中包含的元素个数取决于所有参数序列或 ...
- sql-向已有数据的表添加约束
语法: alter table 表名 with nocheck add constraint 约束名 约束类型 具体的约束说明 对表中现有的数据不做检查, 只对添加约束后再录入的数据进行检查. 例子: ...