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


    传送门: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
    ", ans); 
            } else {
                T.splay(x);
                T.val[x] = deal(y, z);
                T.up(x); 
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    el-input 标签中密码的显示和隐藏
    java 使用RedisTemplate实现Redis事务
    mac 安装 Java 环境
    Snowflake 分布式UUID
    lsof 查看端口使用时刻
    nginx.pid" failed (2: No such file or directory)
    解决Redis之MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist
    Linux环境下 Jna 解决so依赖文件not found
    Ubuntu mysql 在线安装
    Linux中为什么执行自己的程序要在前面加./
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170707_8.html
Copyright © 2020-2023  润新知