首页 > 其他分享 >「解题报告」UOJ671 [UNR #5] 诡异操作

「解题报告」UOJ671 [UNR #5] 诡异操作

时间:2023-05-19 10:58:07浏览次数:45  
标签:UNR qb log int UOJ671 mid qa 解题 复杂度

这题怎么这么多差评啊?哦卡常啊,没事了。

发现两个操作都是只增不减,显然势能线段树。

考虑维护区间按位与,线段树上维护每一位上有多少个 \(1\),按位与就是区间赋 \(0\),对于区间除法暴力重构。直接暴力维护即可做到 \(O((n + q) \log n \log V)\) 的复杂度。但是 \(\log V = 128\),顶两个 \(\log\),哈哈!

考虑优化。注意到叶子处的数都很小,即数很多而值域很小。那么我们考虑按照值域维护,而不是按照每一位维护。我们将出现次数的每一位维护一个 int128,合并时可以直接模拟二进制加法,区间赋 \(0\) 也可以直接维护一个标记实现,这样 pushUp 的复杂度变为了 \(O(\log len)\),而不是 \(O(\log V)\)。这样我们操作 \(2\) 的复杂度变为了 \(O(q \log^2 n)\),可以通过。但是操作 \(1\) 仍然是 \(O(n \log n \log V)\) 啊?实际上,进一步分析会发现操作 \(1\) 的总复杂度为 \(O(n \log V)\)。

具体来讲,就是考虑势能线段树的分析方法。简单设一个节点的势能函数为当前区间内 \(\log a_i\) 最大值。区间修改造成的贡献肯定是 \(O(q \log^2 n)\),对于非区间修改造成的贡献,一定会使得区间内所有 \(\log a_i\) 都减少 \(1\),那么最大值就会减小 \(1\)。而第 \(i\) 个点的 pushUp 复杂度为 \(O(\log len_i)\),这样复杂度总和就应该为 \(O(\log V \sum \log len_i)\)。对于 \(T(n) = \sum \log a_i\) 我们有 \(T(n) = 2T(\frac{n}{2}) + O(\log n)\),主定理或打表可知 \(T(n) = \Theta(n)\),那么这样这部分的复杂度就是 \(O(n \log V)\) 了。

于是总复杂度就是 \(O(n \log V + q \log^2 n)\)。

然后 注 意 常 数 优 化 。(比如不要维护区间和,等查询的时候再直接求;用 vector 减少内存不连续访问)

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 600005;
typedef __uint128_t u128;
const u128 UINT128_MAX = ((u128) ULLONG_MAX << 64 | ULLONG_MAX);
inline u128 read() {
    static char buf[100];
    scanf("%s", buf);
    u128 res = 0;
    for (int i = 0; buf[i]; ++i) {
        res = res << 4 | (buf[i] <= '9' ? buf[i] - '0' : buf[i] - 'a' + 10);
    }
    return res;
}
inline void output(u128 res) {
    if (res >= 16)
        output(res / 16);
    putchar(res % 16 >= 10 ? 'a' + res % 16 - 10 : '0' + res % 16);
}
int n, q;
u128 a[MAXN];
vector<u128> val[MAXN << 2];
u128 tag[MAXN << 2];
bool empty[MAXN << 2];
#define lc (i << 1)
#define rc (i << 1 | 1)
__attribute__((always_inline)) inline void pushUp(int i) {
    u128 x = 0; 
    auto &o = val[i], &p = val[lc], &q = val[rc];
    empty[i] = empty[lc] && empty[rc];
    for (int j = 0; j < p.size(); j++) {
        o[j] = p[j] ^ q[j] ^ x;
        x = (p[j] & x) | (q[j] & x) | (p[j] & q[j]);
    }
    o[p.size()] = x;
}
__attribute__((always_inline)) inline void addTag(int i, u128 x) {
    tag[i] &= x;
    for (int j = 0; j < val[i].size(); j++) val[i][j] &= x;
}
__attribute__((always_inline)) inline void pushDown(int i) {
    while (~tag[i])
        addTag(lc, tag[i]), addTag(rc, tag[i]), tag[i] = UINT128_MAX;
}
void build(int i = 1, int l = 1, int r = n) {
    tag[i] = UINT128_MAX;
    if (l == r) {
        val[i].push_back(a[l]);
        empty[i] = val[i][0] == 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(lc, l, mid), build(rc, mid + 1, r);
    val[i].resize(val[lc].size() + 1);
    pushUp(i);
}
void updateAnd(int qa, int qb, u128 qv, int i = 1, int l = 1, int r = n) {
    if (empty[i]) return;
    if (qa <= l && r <= qb) {
        addTag(i, qv);
        return;
    }
    int mid = (l + r) >> 1;
    pushDown(i);
    if (qa <= mid) updateAnd(qa, qb, qv, lc, l, mid);
    if (qb > mid) updateAnd(qa, qb, qv, rc, mid + 1, r);
    pushUp(i);
}
void updateDiv(int qa, int qb, u128 qv, int i = 1, int l = 1, int r = n) {
    if (empty[i]) return;
    if (l == r) {
        empty[i] = (val[i][0] /= qv) == 0;
        return;
    }
    int mid = (l + r) >> 1;
    pushDown(i);
    if (qa <= mid) updateDiv(qa, qb, qv, lc, l, mid);
    if (qb > mid) updateDiv(qa, qb, qv, rc, mid + 1, r);
    pushUp(i);
}
u128 sum(int qa, int qb, int i = 1, int l = 1, int r = n) {
    if (qa <= l && r <= qb) {
        u128 ret = 0;
        for (int j = 0; j < val[i].size(); j++) {
            ret += val[i][j] << j;
        }
        return ret;
    }
    int mid = (l + r) >> 1;
    pushDown(i);
    if (qb <= mid) return sum(qa, qb, lc, l, mid);
    if (qa > mid) return sum(qa, qb, rc, mid + 1, r);
    return sum(qa, qb, lc, l, mid) + sum(qa, qb, rc, mid + 1, r);
}
int main() {
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++) {
        a[i] = read();
    }
    int m = n; n = 1;
    while (n < m) n <<= 1;
    build();
    while (q--) {
        int op, l, r; scanf("%d%d%d", &op, &l, &r);
        if (op == 1) {
            u128 x = read();
            if (x != 1) updateDiv(l, r, x);
        } else if (op == 2) {
            updateAnd(l, r, read());
        } else {
            output(sum(l, r)), putchar('\n');
        }
    }
    return 0;
}

标签:UNR,qb,log,int,UOJ671,mid,qa,解题,复杂度
From: https://www.cnblogs.com/apjifengc/p/17414272.html

相关文章

  • 一篇看懂递归的套路解题法
    递归所谓递归,不过是将一个复杂问题分解为一个更小的问题进行求解,在这里我们不再扯太多犊子了,网上有太多递归的介绍让人眼花缭乱摸不着头脑,我们直接开始讲解递归的解体思路。第一步:求解最基本问题并将其返回这一步也就是网上所谓的递归出口,但是个人认为递归出口不太能很好的描述......
  • 「解题报告」P3703 [SDOI2017]树点涂色
    有趣题,代码超好写,而且思路超有趣!!!首先发现操作1的操作都是某个点到根,不难发现这样每种颜色一定对应着树上的一条链。那么操作2可以直接树上查分求答案,这样我们只需要考虑维护每个点到根的链的数量了。怎么维护链的数量?发现这个操作1长得和LCT的Access操作一模一样啊,所......
  • Unreal Engine 大象无形学习笔记(第二部分:虚幻引擎浅析)
     Q1.虚幻引擎的Main函数在哪?LaunchWindows.cpp中找到WinMain。Q2.虚幻引擎为什么要引入模块机制?编辑器模式、发布模式要单独配置非常麻烦。工具:UnrealBuildTool包含大模块:Runtime、Development、Editor、Plugin每个模块包含:Public、Private文件夹,.build.cs文件作用......
  • [AGC013C] Ants on a Circle 解题报告
    洛谷题面AT题面CF625F先考虑弱化版,若是不考虑编号怎么办。这个问题有一个很经典的结论,碰撞等同穿过,所以直接算出每个点按照指定方向走,在\(t\)秒后的位置即可。现在多了一个编号,因为是碰撞,所以两个点的相对位置是相同的,即\(x\)号点原来是\(y\)号点顺时针方向的第几个点,......
  • openwrt ping: sendto: Network unreachable解决办法
    root@OpenWrt:/#pingzhihu.comPINGzhihu.com(103.41.167.234):56databytesping:sendto:Networkunreachable这个错误一般是由于网关配置错误导致的通过 route 查看路由表root@OpenWrt:/#routeKernelIProutingtableDestinationGatewayGenm......
  • Unreal Engine 大象无形学习笔记 (第一部分:虚幻C++编程)
    Q1.什么时候继承自UObject类,什么时候声明纯C++类?UObject自带功能:1.垃圾收集:继承自UObject并被标记为UProperty的变量,会被引擎自动进行生命周期管理。2.Referenceupdating引用自动更新3.反射4.序列化:纯C++类也可以手动实现5.Automaticupdatingofdefaultproperty......
  • CentOS7 虚拟机安装后,网络失败 connect network is unreachable 解决方法
    0001.CentOS7虚拟机安装后,网络失败connectnetworkisunreachable解决方法1590阅读0评论2点赞 connect network is unreachable  一般是网上设置问题,需要进行如下修改:一、虚拟机修改网络配置:1、一般测试虚拟机,建议设置网络为桥接模式,这样跟开发机或......
  • [NOI2018] 归程 解题报告
    题面步行的最小距离很容易求,dij随便求一下每个点的最短路,然后找到与\(v\)能相互坐车到达的点,对这些点的最短路都有可能是答案,取个\(\min\)即可。所以本题最大的问题是怎么找到在水位线为\(p\)时,与\(v\)能相互坐车到达的点。可以想到只保留海拔大于\(p\)的边,因为只要考......
  • 问题解决:TNS-12543: TNS:destination host unreachable
    环境:11.2.0.3ADG(db11g\db11gadg\db11gcas)在自己先前克隆后的环境互相tnsping报错。tnsping本机ok,tnsping其他机器均报错:[oracle@db11g~]$tnspingjingyuTNSPingUtilityforLinux:Version11.2.0.3.0-Productionon13-MAY-202308:09:11Copyright(c)1997,......
  • netty运行测试类时报错:Unrecognized option: --illegal-access=deny
    netty(4.1.42.Final )运行netty-buffer模块测试类时报错:Unrecognizedoption:--illegal-access=deny Unrecognizedoption:--illegal-access=denyError:CouldnotcreatetheJavaVirtualMachine.Error:Afatalexceptionhasoccurred.Programwillexit.解题思路:1、......