您的位置:首页 > 其它

省队集训Day1 睡觉困难综合征

2017-07-07 23:21 387 查看
传送门:https://www.luogu.org/problem/show?pid=3613

【题解】

按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做。

写棵LCT,维护正反两种权值,每个维护2种,代表全0的输出和全1的输出。

然后直接上LCT即可。

权值的合并有点trick,可以参考代码,需要压位。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e5 + 10;
const int mod = 1e9+7;

int n, m, K;

struct node {
ull p0, p1;
node () {}
node (ull p0, ull p1) : p0(p0), p1(p1) {}
friend node operator + (node a, node b) {
return node( (a.p0 & b.p1) | ((~a.p0) & b.p0), (a.p1 & b.p1) | ((~a.p1) & b.p0) );
}
};

inline node deal(int op, ull x) {
if(op == 1) return node(0, x);
if(op == 2) return node(x, ull(-1));
if(op == 3) return node(x, ~x);
}

struct LCT {
int ch[M][2], fa[M];
bool rev[M];
node w[M][2], val[M];
# define ls ch[x][0]
# define rs ch[x][1]
inline void up(int x) {
if(!x) return ;
w[x][0] = w[x][1] = val[x];
if(ls) w[x][0] = w[ls][0] + w[x][0], w[x][1] = w[x][1] + w[ls][1];
if(rs) w[x][0] = w[x][0] + w[rs][0], w[x][1] = w[rs][1] + w[x][1];
}
inline void pushrev(int x) {
if(!x) return ;
rev[x] ^= 1;
swap(ch[x][0], ch[x][1]);
swap(w[x][0], w[x][1]);
}
inline void down(int x) {
if(!x || !rev[x]) return ;
pushrev(ls); pushrev(rs);
rev[x] = 0;
}
# undef ls
# undef rs
inline bool isrt(int x) {
return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
}
inline void rotate(int x) {
int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1;
if(!isrt(y)) ch[z][ch[z][1] == y] = x;
fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
up(y); up(x);
}
int st[M];
inline void splay(int x) {
int stn = 0, tx = x;
while(!isrt(tx)) st[++stn] = tx, tx = fa[tx];
st[++stn] = tx;
for (int i=stn; i; --i) down(st[i]);
while(!isrt(x)) {
int y = fa[x], z = fa[y];
if(!isrt(y)) {
if((ch[z][0] == y)^(ch[y][0] == x)) rotate(x);
else rotate(y);
}
rotate(x);
}
}

inline int access(int x) {
int t = 0;
for (; x; t = x, x = fa[x]) {
splay(x);
ch[x][1] = t;
up(x);
}
return t;
}

inline void makeroot(int x) {
access(x); splay(x); pushrev(x);
}

inline void link(int x, int y) {
makeroot(y); fa[y] = x;
}
}T;

# define bit(x, i) (((x) >> (i)) & 1)

int main() {
//    freopen("sleep.in", "r", stdin);
//    freopen("sleep.out", "w", stdout);
scanf("%d%d%d", &n, &m, &K);
for (int i=1, op; i<=n; ++i) {
ull x;
scanf("%d%llu", &op, &x);
T.val[i] = T.w[i][0] = T.w[i][1] = deal(op, x);
T.ch[i][0] = T.ch[i][1] = T.fa[i] = T.rev[i] = 0;
}
for (int i=1, u, v; i<n; ++i) {
scanf("%d%d", &u, &v);
T.link(u, v);
}
int op, x, y; ull z, tx, ty, ans, t;
while(m--) {
scanf("%d%d%d%llu", &op, &x, &y, &z);
if(op == 1) {
ans = 0; t = 0;
T.makeroot(x); T.access(y); T.splay(y);
tx = T.w[y][0].p0, ty = T.w[y][0].p1;
for (int i=63; ~i; --i) {
if(bit(tx, i)) ans |= (1ull << i);
else if(bit(ty, i)) {
if(t + (1ull << i) <= z) t = t + (1ull << i), ans |= (1ull << i);
}
}
printf("%llu\n", ans);
} else {
T.splay(x);
T.val[x] = deal(y, z);
T.up(x);
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: