洛谷P3613 睡觉困难综合征
题解
人生第一道由乃……
做这题之前应该先去把这一题给切掉->这里
我的题解->这里
然后先膜一波zsy大佬和flashhu大佬
大体思路就是先吧全0和全1的都跑答案,然后按位贪心
我一开始想到的是每一次split,然后直接一个一个跑
后来发现时间复杂度肯定爆炸……
看了看网上其他的,发现说的都不怎么清楚……结果硬是理解了好久才明白……
先考虑一下LCT维护什么
定义$f0$为全0走过一条路径之后的答案,$f1$表示全1走过一条路径之后的答案
LCT需要维护的是splay中以x为根的子树里,从前往后遍历(即中序遍历)的$f0$和$f1$以及从后往前(即与前面完全相反的顺序)的$f0$和$f1$
比如有一棵splay,x是其中一个点,它在splay中有两个儿子,左儿子y和右儿子z,那么从前往后遍历就是路径y->x->z,从后往前就是路径z->x->y
然后思考,如果已经有了两个区间,该如何合并他们
假如说我们有两段计算出答案的区间,分别对应f0,f1和g0,g1。我们设合并后的答案是h0,h1,那么有如下式子:
$h0=(~f0&g0)+(f0&g1)$
$h1=(~f1&g0)+(f1&g1)$
为啥?
全0走到最后的话,先考虑两种情况
全0走到中间等于1的那几位,走后一半的答案等同于全1走后一半的这几位的答案
全0走到中间等于0的那几位,走后一半的答案等同于全0走后一半的这几位的答案
只需要把这两个答案加起来即可
(ps:这里默认f为前一半的答案,g为后一半的答案)
全1走到最后同理
然后就是几个细节
1.pushdown的时候因为有翻转标记,从前往后走和从后往前走的答案也要交换
2.按位贪心用1做位运算的时候,记得把1设成unsigned long long(简单来说就是设一个ull变量让它等于1)(我就是因为一开始直接用1做位运算结果死都调不出来……)
// luogu-judger-enable-o2
//minamoto
#include<iostream>
#include<cstdio>
#define ll unsigned long long
using std::swap;
using std::cout;
using std::endl;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline ll read(){
#define num ch-'0'
char ch;bool flag=;ll res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char obuf[<<],*o=obuf;
void print(ll x){
if(x>) print(x/);
*o++=x%+;
}
const int N=;
struct node{
ll f0,f1;
inline node operator +(const node &b)const
{
node a;
a.f0=(~f0&b.f0)|(f0&b.f1);
a.f1=(~f1&b.f0)|(f1&b.f1);
return a;
}
}f[N],l[N],r[N];
int fa[N],ch[N][],s[N],rev[N],top,tot;
int ver[N<<],head[N],Next[N<<];
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
inline bool isroot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
#define ls ch[x][0]
#define rs ch[x][1]
inline void pushup(int x){
l[x]=r[x]=f[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];
}
inline void pushr(int x){
swap(ls,rs),swap(l[x],r[x]),rev[x]^=;
}
inline void pushdown(int x){
if(rev[x]&&x){
pushr(ls),pushr(rs),rev[x]=;
}
}
void rotate(int x){
int y=fa[x],z=fa[y],d=ch[y][]==x;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
fa[x]=z,fa[y]=x,fa[ch[x][d^]]=y,ch[y][d]=ch[x][d^],ch[x][d^]=y,pushup(y);
}
void splay(int x){
s[top=]=x;for(int i=x;!isroot(i);i=fa[i]) s[++top]=fa[i];
while(top) pushdown(s[top--]);
for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){
if(!isroot(y))
((ch[y][]==x)^(ch[z][]==y))?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x){
for(int y=;x;x=fa[y=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);
}
void dfs(int u){
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v==fa[u]) continue;
fa[v]=u,dfs(v);
}
pushup(u);
}
int main(){
//freopen("testdata.in","r",stdin);
int n=read(),m=read(),k=read();
for(int i=;i<=n;++i){
int x=read();ll y=read();
switch(x){
case :f[i]=(node){,y};break;
case :f[i]=(node){y,~};break;
case :f[i]=(node){y,~y};break;
}
}
for(int i=;i<n;++i){
int u=read(),v=read();add(u,v);
}
dfs();
while(m--){
int opt=read(),x=read(),y=read();ll z=read();
if(opt&){
split(x,y);ll ans=,e=;
for(int i=k-;i>=;--i){
if(l[y].f0&(e<<i)) ans|=e<<i;
else if((l[y].f1&(e<<i))&&z>=(e<<i)) ans|=e<<i,z^=e<<i;
}
print(ans),*o++='\n';
}
else{
switch(y){
case :f[x]=(node){,z};break;
case :f[x]=(node){z,~};break;
case :f[x]=(node){z,~z};break;
}
splay(x);
}
}
fwrite(obuf,o-obuf,,stdout);
return ;
}
洛谷P3613 睡觉困难综合征的更多相关文章
- 【刷题】洛谷 P3613 睡觉困难综合征
题目背景 刚立完Flag我就挂了WC和THUWC... 时间限制0.5s,空间限制128MB 因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了 由于二周目 ...
- 洛谷P3613 睡觉困难综合征(LCT)
题目: P3613 睡觉困难综合症 解题思路: LCT,主要是维护链上的多位贪心答案,推个公式:分类讨论入0/1的情况,合并就好了(公式是合并用的) 代码(我不知道之前那个为啥一直wa,改成结构体就好 ...
- 洛谷P3613 睡觉困难综合征(LCT,贪心)
洛谷题目传送门 膜拜神犇出题人管理员!!膜拜yler和ZSY!! 没错yler连续教我这个蒟蒻写起床困难综合症和睡觉困难综合症%%%Orz,所以按位贪心的思路可以继承下来 这里最好还是写树剖吧,不过我 ...
- [洛谷]P3613 睡觉困难综合征
题目大意:给出一棵n个点的树,每个点有一个运算符(与.或.异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对 ...
- [洛谷P3613]睡觉困难综合症
写码30min,调码3h的题.. 好在最后查出来了 , , n, x, y, z); 改成了 , , n, mark[x], y, z); 然后$40\rightarrow 100$ #include ...
- 洛谷3613睡觉困难综合征(LCT维护链信息(前后缀)+贪心)
这个题目还是很好啊QWQ很有纪念意义 首先,如果在序列上且是单次询问的话,就是一个非常裸的贪心了QWQ这也是NOI当时原题的问题和数据范围 我们考虑上树的话,应该怎么做? 我的想法是,对于每一位建一个 ...
- [bzoj3668][Noi2014]起床困难综合症/[洛谷3613]睡觉困难综合症
来自FallDream的博客,未经允许,请勿转载,谢谢. 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm 一直坚持与起床困难综 ...
- P3613 睡觉困难综合征(LCT + 位运算)
题意 NOI2014 起床困难综合症 放在树上,加上单点修改与链上查询. 题解 类似于原题,我们只需要求出 \(0\) 和 \(2^{k - 1} - 1\) 走过这条链会变成什么值,就能确定每一位为 ...
- [P3613]睡觉困难综合征
Description: 给定一个n个点的树,每个点有一个操作符号 "&" "|" "^" ,以及一个权值 要求支持以下操作: 1. ...
随机推荐
- DDA算法
[DDA算法] Digital Differential Analyzer,DDA算法是一种线段扫描转换算法.(线段光栅化算法) DDA算法优缺点: 1.消除了直线方程中的乘法计算,而在x.y方向使用 ...
- Cassandra读写性能测试
1. 测试目的 测试Cassandra集群读写TPS的极值,确定Cassandra读写性能. 2. 测试环境 2.1 硬件信息 CPU 8核 Intel(R) Xeon(R) CPU E5-2650 ...
- JS的事件汇总
一.前言 事件的绑定触发有很多种方法,我们如何选择呢? 很多时候,我们会使用鼠标事件,但是鼠标事件只能在PC设备上使用,当我们需要对不同设备兼容时怎么办呢? 二.正文 1. 事件的几个概念: 事件流: ...
- 第十一条理解objc_masgSend的作用
Objetive-C最基本的的东西就是它的消息机制.Objective-C运行时的最基本的东西就是 objc_msgSend, 它就是负责发送一个消息给对象的C函数. 当你写下面这样的代码时: ...
- 647. Palindromic Substrings 互文的子字符串
[抄题]: Given a string, your task is to count how many palindromic substrings in this string. The subs ...
- HowTo: Xen 4.1.3 Windows 8 HVM domU with Intel HD4000 VGA Passthrough on Debian Wheezy
http://linux-bsd-sharing.blogspot.com/2012/10/howto-xen-413-windows-8-hvm-domu-with.html Update 05/0 ...
- java的static块及相关内容
原文地址:http://blog.csdn.NET/lubiaopan/article/details/4802430 感谢原作者! static{}(即static块),会在类被加载的时候执 ...
- code1085 数字游戏
划分dp 把环变链(读入4 3 -1 2变成4 3 -1 2 4 3 -1 2) 设dp[i][j][k]为把i~j分成k份,各部分内的数字相加,相加所得的k个结果对10取模后再相乘,最终得到的一个数 ...
- IE6,7,8在boostrap中兼容h5和css3
IE6.7.8版本(IE9以下版本)浏览器兼容html5新增的标签,引入下面代码文件即可: <script src="https://oss.maxcdn.com/libs/html5 ...
- 用Collections升降排序
//期末从业人员 总收入 资产总计等 升降 排序 if("qmcyry".equals(sss)){ if("desc".equals(orders)){ Co ...