\(\color{#0066ff}{ 题目描述 }\)

由乃这个问题越想越迷糊,已经达到了废寝忘食的地步。结果她发现……晚上睡不着了!只能把自己的一个神经元(我们可以抽象成一个树形结构)拿出来,交给Deus。

这个神经元是一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示。

为了治疗失眠,Deus可以将一些神经递质放在点x上,初始的刺激值是\(v_0\)。然后v依次经过从x到y的所有节点,每经过一个点i,v就变成v opti xi,所以他想问你,最后到y时,希望得到的刺激值尽可能大,所以最大值的v可以是多少呢?当然由于初始的神经递质的量有限,所以给定的初始值\(v_0\)必须是在[0,z]之间。Deus每次都会给你3个数,x,y,z。

不过,Deus为了提升治疗效果,可能会对一些神经节点进行微调。在这种情况下,也会给三个数x,y,z,意思是把x点的操作修改为y,数值改为z

\(\color{#0066ff}{输入格式}\)

第一行三个数n,m,k。k的意义是每个点上的数,以及询问中的数值z都 \(<2^k\)。之后n行,每行两个数x,y表示该点的位运算编号以及数值

之后n - 1行,每行两个数x,y表示x和y之间有边相连

之后m行,每行四个数,Q,x,y,z表示这次操作为Q(1位询问,2为更改),x,y,z意义如题所述

\(\color{#0066ff}{输出格式}\)

对于每个操作1,输出到最后可以造成的最大刺激度v

\(\color{#0066ff}{输入样例}\)

5 5 3
1 7
2 6
3 7
3 6
3 1
1 2
2 3
3 4
1 5
1 1 4 7
1 1 3 5
2 1 1 3
2 3 3 3
1 1 3 2 2 2 2
2 2
2 2
1 2
2 2 2 2
1 2 2 2

\(\color{#0066ff}{输出样例}\)

7
1
5 3

\(\color{#0066ff}{数据范围与提示}\)

对于30%的数据,n,m <= 1

对于另外20%的数据,k <= 5

对于另外20%的数据,位运算只会出现一种

对于100%的数据,0 <= n , m <= 100000 , k <= 64

\(\color{#0066ff}{ 题解 }\)

位运算神仙题qwq

要一种支持单点修改,树链查询的东东维护,就LCT啦

要使最后结果最大,显然可以按位贪心

用0跑一边,用1跑一边,再根据给的范围,看当前位那个更优

这样应该可以拿到50pts

其实发现,可以所有一起跑

即64个二进制位,全是0跑出来的结果和全是1跑出来的结果,到最后再贪心

因为LCT的Splay有翻转这种东西,而对于\(x-y\),从y到x和从x到y的结果是不一定相同的!

因此我们要记录两个值, 一个是从左到右用全0和全1跑出来的值,一个是从右到左用全0和全1跑出来的值

假设我们已经知道了两个区间的值,如何合并呢

设左边的为f0,f1右边的为g0,g1,合并后的结果为h0,h1

那么有

h0=(~f0&g0)+(f0&g1)

h1=(~f1&g0)+(f1&g1)

这是个啥东西。。。

全0通过左区间之后,就是f0,考虑里面1的贡献和0的贡献。

0的贡献即g0通过后有1的位置,但是要合并还得满足从f0通过是0,因此把f0取反在按位与一下

就是说只有那些通过左区间为0的位置,经过g0为1,才会产生贡献

1就同理啦

再同理一下,h1也是这样的,然后就直接LCT维护即可了

#include<bits/stdc++.h>
#define LL unsigned long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 1e5 + 10;
struct bit {
LL f0, f1;
bit(LL f0 = 0, LL f1 = 0): f0(f0), f1(f1) {}
friend bit operator + (const bit &a, const bit &b) {
return bit((~a.f0 & b.f0) | (a.f0 & b.f1), (~a.f1 & b.f0) | (a.f1 & b.f1));
}
};
LL f[maxn];
struct node {
node *ch[2], *fa;
bit f, l, r;
int rev;
node(int rev = 0): rev(rev) { ch[1] = ch[0] = fa = NULL; }
void trn() { std::swap(ch[0], ch[1]), std::swap(l, r), rev ^= 1; }
void upd() {
l = r = f;
if(ch[0]) l = ch[0]->l + l, r = r + ch[0]->r;
if(ch[1]) l = l + ch[1]->l, r = ch[1]->r + r;
}
void dwn() {
if(!rev) return;
if(ch[0]) ch[0]->trn();
if(ch[1]) ch[1]->trn();
rev = 0;
}
bool isr() { return this == fa->ch[1]; }
bool ntr() { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
}pool[maxn];
struct EDGE {
int to;
EDGE *nxt;
EDGE(int to = 0, EDGE *nxt = NULL): to(to), nxt(nxt) {}
}*head[maxn];
void rot(node *x) {
node *y = x->fa, *z = y->fa;
bool k = x->isr(); node *w = x->ch[!k];
if(y->ntr()) z->ch[y->isr()] = x;
(x->ch[!k] = y)->ch[k] = w;
(y->fa = x)->fa = z;
if(w) w->fa = y;
y->upd(), x->upd();
}
void splay(node *o) {
static node *st[maxn];
int top;
st[top = 1] = o;
while(st[top]->ntr()) st[top + 1] = st[top]->fa, top++;
while(top) st[top--]->dwn();
while(o->ntr()) {
if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa);
rot(o);
}
}
void access(node *x) {
for(node *y = NULL; x; x = (y = x)->fa)
splay(x), x->ch[1] = y, x->upd();
}
void makeroot(node *x) { access(x), splay(x), x->trn(); }
void split(node *x, node *y) { makeroot(x), access(y), splay(y); }
void add(int from, int to) {
head[from] = new EDGE(to, head[from]);
} void dfs(int x, int fa) {
for(EDGE *i = head[x]; i; i = i->nxt) {
if(i->to == fa) continue;
pool[i->to].fa = pool + x;
dfs(i->to, x);
}
}
int n, m, k;
int main() {
n = in(), m = in(), k = in();
for(int i = 1; i <= n; i++) {
int p = in(); LL x = in();
if(p == 1) pool[i].f = bit(0, x);
if(p == 2) pool[i].f = bit(x, ~0);
if(p == 3) pool[i].f = bit(x, ~x);
}
int x, y;
for(int i = 1; i < n; i++) x = in(), y = in(), add(x, y), add(y, x);
dfs(1, 0);
while(m --> 0) {
int p = in(), x = in(), y = in(); LL val = in();
if(p & 1) {
split(pool + x, pool + y);
LL ans = 0, o = 1;
for(int i = k - 1; i >= 0; i--) {
if(pool[y].l.f0 & (o << i)) ans |= (o << i);
else if((pool[y].l.f1 & (o << i)) && val >= (o << i)) val ^= (o << i), ans |= (o << i);
}
printf("%llu\n", ans);
}
else {
if(y == 1) pool[x].f = bit(0, val);
if(y == 2) pool[x].f = bit(val, ~0);
if(y == 3) pool[x].f = bit(val, ~val);
splay(pool + x);
}
}
return 0;
}

P3613 睡觉困难综合征 LCT+贪心+位运算的更多相关文章

  1. 洛谷P3613 睡觉困难综合征(LCT)

    题目: P3613 睡觉困难综合症 解题思路: LCT,主要是维护链上的多位贪心答案,推个公式:分类讨论入0/1的情况,合并就好了(公式是合并用的) 代码(我不知道之前那个为啥一直wa,改成结构体就好 ...

  2. 【刷题】洛谷 P3613 睡觉困难综合征

    题目背景 刚立完Flag我就挂了WC和THUWC... 时间限制0.5s,空间限制128MB 因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了 由于二周目 ...

  3. P3613 睡觉困难综合征(LCT + 位运算)

    题意 NOI2014 起床困难综合症 放在树上,加上单点修改与链上查询. 题解 类似于原题,我们只需要求出 \(0\) 和 \(2^{k - 1} - 1\) 走过这条链会变成什么值,就能确定每一位为 ...

  4. 洛谷P3613 睡觉困难综合征(LCT,贪心)

    洛谷题目传送门 膜拜神犇出题人管理员!!膜拜yler和ZSY!! 没错yler连续教我这个蒟蒻写起床困难综合症和睡觉困难综合症%%%Orz,所以按位贪心的思路可以继承下来 这里最好还是写树剖吧,不过我 ...

  5. [洛谷]P3613 睡觉困难综合征

    题目大意:给出一棵n个点的树,每个点有一个运算符(与.或.异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对 ...

  6. 洛谷P3613 睡觉困难综合征

    传送门 题解 人生第一道由乃…… 做这题之前应该先去把这一题给切掉->这里 我的题解->这里 然后先膜一波zsy大佬和flashhu大佬 大体思路就是先吧全0和全1的都跑答案,然后按位贪心 ...

  7. [P3613]睡觉困难综合征

    Description: 给定一个n个点的树,每个点有一个操作符号 "&" "|" "^" ,以及一个权值 要求支持以下操作: 1. ...

  8. Luogu P2114[NOI2014]起床困难综合症 【贪心/位运算】By cellur925

    题目传送门 所以NOI的题现在简单惹? 30分做法:枚举开始的权值,n²过掉. 100分做法:竟然是贪心qwq.因为我们的计算背景是二进制下,所以我们贪心地想让每一位都是1.我们现在需要解决的问题,就 ...

  9. P3613 睡觉困难综合征(码力)

    Luogu3613 实现细节较多,详见代码 #include<cstdio> #include<iostream> #include<cstring> #inclu ...

随机推荐

  1. Jlink flash 烧录HEX 程序

    一般Jlink版本 和 Jag(硬件)最好匹配 安装Jlink 时,IAR的工具包也可以顺带安装. 有源码: IAR 可以自动选择CPU型号,代码直接Download and debug https: ...

  2. SQL属性第一个值不被选中,属性默认第一个值

    把 Please Choose Color 属性名设置为不可选的 UPDATE `products_attributes` SET `attributes_display_only` = '1' WH ...

  3. mac 下 配置appium +ios真机环境

    mac系统:10.11.6 xcode:7 appium:1.5.3 iphone: 6 p 1.搭建 appium 安卓的环境: 1.jdk 2.sdk 3.appium 4.配置环境变量 mac下 ...

  4. 图解缓存淘汰算法二之LFU

    1.概念分析 LFU(Least Frequently Used)即最近最不常用.从名字上来分析,这是一个基于访问频率的算法.与LRU不同,LRU是基于时间的,会将时间上最不常访问的数据淘汰;LFU为 ...

  5. typescript整合到vue中的详细介绍,ts+vue一梭子

    通过vue-cli命令行安装vue项目,注意不要eslint 安装依赖 cnpm install typescript --save-dev cnpm install ts-loader --save ...

  6. java 多线程系列基础篇(九)之interrupt()和线程终止方式

    1. interrupt()说明 在介绍终止线程的方式之前,有必要先对interrupt()进行了解.关于interrupt(),java的djk文档描述如下:http://docs.oracle.c ...

  7. 类型:.net;问题:iis注册;结果:.net4.0注册到IIS ,重新注册IIS ,iis注册

    .net4.0注册到IIS ,重新注册IIS ,iis注册   IIS和.netfw4.0安装顺序是从前到后,如果不小心颠倒了,无所谓. 打开程序-运行-cmd:输入一下命令重新注册IIS C:\WI ...

  8. Plist文件存储

    一.Plilst存储简介 (1)只能储存NSData.NSNumber.NSDictionary.NSString.NSDate.NSArray.BOOL等数据类型,如果需要存储其他NSObject类 ...

  9. Using JConsole

    Using JConsole 转自 https://docs.oracle.com/javase/8/docs/technotes/guides/management/jconsole.html Th ...

  10. POJ 1151 扫描线 线段树

    题意:给定平面直角坐标系中的N个矩形,求它们的面积并. 题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序.记录所有的y坐标以后排序离散化.离 ...