首页 > 其他分享 >sol P9747 结论 二维数点

sol P9747 结论 二维数点

时间:2024-02-27 09:36:10浏览次数:12  
标签:P9747 int res 数点 sol back inline st out

从小号搬一下。

key observation:若一个区间合法,则最后覆盖整个区间的数一定是它的按位或和。

证明很简易:操作不会影响区间按位或和。

然后分类讨论得到如下结论:

  • 区间内有 \(\ge 2\) 个等于区间按位或和的数时,有解。

  • 区间内有 \(1\) 个等于区间按位或和的数,同时区间内有不与这个数位置有交的子区间,且其按位或和等于这个数时,有解。

  • 其他情况无解。

考虑统计。一个经典结论,对于每个固定的左端点 \(x\),会有 $ O(\log V)$ 种不同的区间按位或和取值。所以对于 \(x\),会有 $ O(\log V)$ 个右端点的取值区间 \([l,r]\)。我们可以表示成三元组 \((x,l,r)\)。

把三元组差分到 \(l\) 和 \(r + 1\) 上,把询问挂在右端点上,离线下来扫描线。线段树和 set 维护两种情况:答案子区间右端点为 \(r\)、答案子区间右端点为当前询问右端点。

关于预处理三元组,按照结论模拟即可。

时间复杂度 \(O(n\log n\log V)\),空间复杂度 \(O(n\log V)\)。需要一定的卡常技巧。

感觉放代码没什么用,但还是贴上
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x); i <= (y); i++)
#define per(i, x, y) for (int i = (x); i >= (y); i--) 
struct IO {
    static const int inSZ = 1 << 17;
    char inBuf[inSZ], *in1, *in2;
    template<class T> inline __attribute((always_inline))
    T read() {
        if (in1 > inBuf + inSZ - 32) [[unlikely]] {
            auto len = in2 - in1;
            memcpy(inBuf, in1, len);
            in1 = inBuf, in2 = inBuf + len;
            in2 += fread(in2, 1, inSZ - len, stdin);
            if (in2 != inBuf + inSZ) *in2 = 0;
        }
        T res = 0;
        unsigned char c;
        bool neg = 0;
        while ((c = *in1++) < 48) neg = c == 45;
        while (res = res * 10 + (c - 48), (c = *in1++) >= 48);
        return neg ? -res : res;
    }
    static const int outSZ = 1 << 21;
    char outBuf[outSZ], *out;
    template<class T> inline __attribute((always_inline))
    void write(T x) {
        if (out > outBuf + outSZ - 32) [[unlikely]]
            fwrite(outBuf, 1, out - outBuf, stdout), out = outBuf;
        if (!x) return *out++ = 48, void();
        if (x < 0) *out++ = 45, x = -x;
        alignas(2) const char* digits =
        "0001020304050607080910111213141516171819"
        "2021222324252627282930313233343536373839"
        "4041424344454647484950515253545556575859"
        "6061626364656667686970717273747576777879"
        "8081828384858687888990919293949596979899";
        alignas(64) static char buf[20];
        char* p = buf + 20;
        while (x >= 10) memcpy(p -= 2, digits + x % 100 * 2, 2), x /= 100;
        if (x) *--p = 48 + x;
        auto len = buf + 20 - p;
        memcpy(out, p, len), out += len;
    }
    void init() {
        in1 = in2 = inBuf + inSZ;
        out = outBuf;
    }
    ~IO() { fwrite(outBuf, 1, out - outBuf, stdout); }
} IO;
template<class T = int> inline T read() {
    return IO.read<T>();
}
template<class... Args> inline void read(Args&... args) {
    ((args = IO.read<Args>()), ...);
}
template<class T> inline void write(T x, char c = '\n') {
    IO.write(x), *IO.out++ = c;
}
constexpr int N = 2e6 + 5;
int n, q, a[N], ans[N]; vector<array<int, 2>> qq[N], Q[N], v[N];
int NN, t[(int)1e7 + 5];
inline void build() {
	for (int i = 1; i <= n; i++) t[i + NN] = 0;
	for (int i = NN; i; i--) t[i] = t[i << 1] + t[i << 1 | 1]; 
}
inline void upd(int p, int x) {
    t[p + NN] = x;
    for (int i = (p + NN) >> 1; i; i >>= 1) t[i] = max(t[i << 1], t[i << 1 | 1]);
}
inline int qry(int l, int r) {
	int res = 0;
	for (l += NN - 1, r += NN + 1; l ^ r ^ 1; l >>= 1, r >>= 1) {
		if (~l & 1) res = max(res, t[l ^ 1]);
		if (r & 1) res = max(res, t[r ^ 1]);
	} return res;
}
set<int> s; unordered_map<int, vector<int>> mp, bucc;
inline void init() {
    mp.clear();
    rep (i, 1, n + 1) v[i].clear();
    per (i, n, 1) {
        v[i].push_back({i, a[i]}); mp[a[i]].push_back(n - i);
        for (auto to : v[i + 1]) {
            if ((to[1] | a[i]) ^ v[i].back()[1]) {
                v[i].push_back({to[0], to[1] | a[i]});
                mp[v[i].back()[1]].push_back(n - i);
                if (v[i].back()[1] ^ to[1]) mp.erase(to[1]);
            }
        } v[i].push_back({n + 1, 0});
        rep (p, 0, v[i].size() - 2) {
            int l = v[i][p][0], r = v[i][p + 1][0] - 1;
            if (a[l] ^ v[i][p][1]) {
                vector<int> &st = bucc[v[i][p][1]];
                auto it = upper_bound(st.begin(), st.end(), l);
                if (it == st.end()) continue;
                l = *it; if (l <= r) Q[l].push_back({1, i}), Q[r + 1].push_back({0, i});
                continue;
            }
            vector<int> &st = mp[v[i][p][1]];
            auto it = lower_bound(st.begin(), st.end(), n - l);
            if (it == st.begin()) continue; it = prev(it);
            for (auto to : v[n - *it]) if (to[1] == v[i][p][1]) {
                l = to[0]; break;
            }
            if (l <= r) Q[l].push_back({1, i}), Q[r + 1].push_back({0, i});
        }
        v[i].pop_back();
    }
}
inline void solve() {
    n = read(), q = read(); bucc.clear();
    rep (i, 1, n) {
        a[i] = read(), bucc[a[i]].push_back(i);
        qq[i].clear(), Q[i].clear();
    }
    rep (i, 1, q) {
        int l = read(), r = read();
        qq[r].push_back({l, i}); 
    }  
    init(); NN = 1 << (__lg(n) + 1); build(), s.clear(); s.insert(n + 1);
    rep (i, 1, n) {
        sort(Q[i].begin(), Q[i].end());
        for (auto [op, x] : Q[i]) {
            if (op) s.insert(x);
            else s.erase(x), upd(x, i - x);
        }
        for (auto [l, id] : qq[i]) {
            ans[id] = max(qry(l, i), i - *s.lower_bound(l) + 1);
        }
    }
    rep (i, 1, q) write(max(ans[i], 1));
}
signed main() {
    IO.init();
    int kowen = read(), opunt = read();
    while (kowen--) solve();
    return 0;
}

标签:P9747,int,res,数点,sol,back,inline,st,out
From: https://www.cnblogs.com/kxwenorz/p/18036163

相关文章

  • sol CF587F AC 自动机 根号分治
    注意下文中fail树和trie树的不同。考虑给询问离线,然后差分成\([1,r]-[1,l-1]\)的前缀询问来做。先对于\(s_{1\dotsn}\)建立AC自动机。从左到右扫描询问,当扫描到\(i\)时就对fail树上的子树\(i\)全体\(+1\),使用树状数组维护即可。答案即为\(s_k\)在trie树......
  • 把 Console 部署成 Windows 服务,四种方式总有一款适合你!
    一:背景1.讲故事上周有一个项目交付,因为是医院级项目需要在客户的局域网独立部署。程序:netcore2.0,操作系统:windowsserver2012,坑爹的事情就来了,netcoresdk一直装不上,网上找了资料说需要先安装VisualC++RedistributableforVisualStudio2015,开开心心下载下来又......
  • Solution Set #11
    177qoj7607.TheDoublingGame2首先可以发现对于一个局面,操作到这个局面的方案是唯一的(考虑一条边左右的棋子数量,可以知道这条边的移动方向,删去所有不移动的边之后,每个联通块只有一个点有棋子,而对于只有根有棋子的局面构造显然唯一)据此可以\(\mathcal{O}(n^2)\)DP:设\(f_{u......
  • Solo 开发者周刊 (第5期):打破常规,探索技术新边界
    这里会整合Solo社区每周推广内容、产品模块或活动投稿,每周五发布。在这期周刊中,我们将深入探讨开源软件产品的开发旅程,分享来自一线独立开发者的经验和见解。本杂志开源,欢迎投稿。产品推荐1.新一代的团队协作平台-TeamlinkerTeamlinker是一个集成了不同功能和模块的团队协作......
  • 刘铁猛C#学习笔记19 抽象类、接口与SOLID五大原则
    接口与抽象类是所有高阶面向对象的起点,是学习设计模式的前置条件必须有实践基础之后,才能真正掌握算法、设计模式 设计模式的基础solid五大设计原则(待续)1.单一职责原则singleresponsibilityprinciple2.开放-关闭原则Open-closeprinciple,简称为开闭原则“封装确定的,......
  • lazarus3.0 /fpc3.3.1编译某些控件会出现:Error: Forward declaration not solved xxx
    最近用lazarus3.0/fpc3.3.1时发现原来在lazarus2.2.6/fpc3.2.2能编译安装的控件出现类似下面的提示codebot.text.xml.pas(129,10)Error:Forwarddeclarationnotsolved"NewDocument:IDocument;"解决方法:本例子参照DocumentCreate:IDocument,在实现部分编写过程。{$i......
  • 2.22 闲话 & solution 『虽然我不是神/不像他们无所不能/却总畏惧一语成谶』
    有↑没有↓谁↑能够↓代↑替↓我↑(去考开学的一调)唐氏模拟赛,板子大战,全场都是板子,\(\textT3\)甚至还不如板子,\(byd\)题解居然是用的高贵的\(O(n\logn)\)算欧拉函数,唐\(\text{lxyt}\)复活赛打赢了可以去打\(\text{HEOI2024}\)了,体验名额DZ和xrlong的代码进行了大量对拍,仍......
  • solution-div2contest-D
    题面可以在link看到?大力手玩题!场切了!首先看到这种题,我们一定是先想给定一个树怎么求他的最大独立集。我忘记怎么贪心了,于是考虑DP,设\(f_{u,0/1}\)表示以\(u\)为根的子树中独立集包含或不包含\(u\)这个点的最大独立集大小。转移是显然的,为了下文讲解方便还是在这里写出......
  • Promise.resolve
    Promise.resolve是一个JavaScript方法,用于创建一个以给定值解析的Promise对象。当Promise.resolve方法被调用时,它会返回一个已解析的Promise对象,该对象的状态是已完成(fulfilled)并且其值是传递给Promise.resolve方法的参数。Promise.resolve方法有两种常见用法:传递一个普通值作......
  • Solana 开发学习之通过RPC与Solana交互
    Solana开发学习之通过RPC与Solana交互相关链接https://solana.com/docs/rpc/httphttps://www.jsonrpc.org/specificationhttps://www.json.org/json-en.htmlJSON-RPC2.0规范JSON-RPC是一种无状态、轻量级远程过程调用(RPC)协议。该规范主要定义了几种数据结构及其处......