首页 > 其他分享 >CFgym103260K-Rectangle Painting

CFgym103260K-Rectangle Painting

时间:2023-08-22 18:12:20浏览次数:40  
标签:set limits int max Ans CFgym103260K ans Painting Rectangle

前言

断续地调了一天一夜,终于做出来了!

题目链接-Rectangle Painting

大概就是:给 \(n\) 个集合 \(S_i\),两种操作,

  1. 1 {[l,r],x }l r 向 \(S_l\) 到 \(S_r\) 插入 \(x\)
  2. 2 l r 询问 \(\max\limits_{i=l}^r \{\text{mex}(S_i)\}\)。

但是强制在线!

\(1\le n,l,r\le 2\times 10^5,1\le q\le 10^5,\texttt{10s,1024MiB}\)

解题思路

乍一看很不可做,但是可以尝试枚举答案。

先开 \(N\) 颗线段树,每棵树 \(T_i\) 存储从每个集合里是否有 \(col_i\)。

计算答案时一个节点 \(x\) 的答案 \(Ans_x=\max\limits_{i=l}^r \{\text{mex}(S_i)\}=\max\{Ans_{ls_x},Ans_{rs_x}\}\) ,即两个儿子的答案最大值。

但是维护一个节点的 \(mex\) 是 \(O(n)\) 的,并且不支持懒标记,怎么优化?

先把每个节点 \(j\) 对每个颜色 \(x\) 分为 \(0,1,2\) 三种状态,分别是:

  • \(state_{j,x}=0:\sum\limits_{i=l}^r1[col_x\in S_i]=0\)
  • \(state_{j,x}=1:0 < \sum\limits_{i=l}^r1[col_x\in S_i] < r-l+1\)
  • \(state_{j,x}=2:\sum\limits_{i=l}^r1[col_x\in S_i]=r-l+1\)

即完全没有覆盖,部分覆盖和全覆盖。

于是对于一个点,我们额外维护一个集合 \(A_x\),满足 \(\forall i\in[1,N],i\in A_x\Leftrightarrow state_{x,i}=0 \land state_{\lfloor\frac{x}{2}\rfloor,i}=1\)。

令从节点 \(i\) 到 \(root\) 的路径为 \(p_{i\to root}\)

注意到,一个叶子结点 \(i\) 的 \(\text{mex}\) 就是 \(\max\limits_{j\in p_{i\to root}}\{\min\limits_{k\in A_j}k\}\)。也就是路径上每个点的 \(A\) 的最小值的最大值。不懂的读者可以自己画一画。

这样就可以把之前的柿子 \(Ans_x=\max\{Ans_{ls_x},Ans_{rs_x}\}\) 转化成 \(Ans_x=\min\{\min\limits_{i\in A_x}i,\max\{Ans_{ls_x},Ans_{rs_x}\}\}\)

这样可以每个节点 \(x\) 开一个set存一下 \(A_x\),这样每个节点 pushup() 的时间复杂度就是 \(\log n\) 的,query() 的时间复杂度是 \(\log n\) 的,update() 的时间复杂度是 \(\log^2 n\) 的。

但是,这都是基于对每个颜色操作不交的前提,所以需要使用 set 来在线维护没有被修改的区间,然后对每个区间进行修改。

所以总时间复杂度为 \(O(n\log^2 n)\)。

结束了。

事实上,程序只跑了1s。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int V = 2e5, N = V + 5;

namespace sgt
{
    set<int> s[N << 2];
    int a[N << 2], typ[N << 2];
    void init()
    {
        memset(a, 0x3f, sizeof a);
        for(int i = 0; i <= V; i ++) s[1].insert(i);
        a[1] = 0;
    }
    void pushup(int x, int typ)
    {
        if(typ) return a[x] = (s[x].empty() ? 0x3f3f3f3f : *s[x].begin()), void();
        a[x] = max(a[x << 1], a[x << 1 | 1]);
        if(!s[x].empty()) a[x] = min(a[x], *s[x].begin());   
    }
    void update(int ql, int qr, int l, int r, int x, int g, int v)
    {
        if(ql <= l && r <= qr)
        {
            if(s[x].count(v))
                s[x].erase(v), pushup(x, l == r);
            return;
        }
        int mid = (l + r) >> 1, st = 0;
        if(s[x].count(v)) g = 1, s[x].erase(v);
        if(mid >= ql) update(ql, qr, l, mid, x << 1, g, v), st |= 1;
        if(mid < qr) update(ql, qr, mid + 1, r, x << 1 | 1, g, v), st |= 2;
        if(g)
        {
            if(!(st & 1)) s[x << 1].insert(v), pushup(x << 1, l == mid);
            if(!(st & 2)) s[x << 1 | 1].insert(v), pushup(x << 1 | 1, mid + 1 == r);
        }
        pushup(x, l == r);
    }
    int query(int ql, int qr, int l, int r, int x)
    {
        if(ql <= l && r <= qr)
            return a[x];
        int mid = (l + r) >> 1, ans = 0;
        if(mid >= ql) ans = max(ans, query(ql, qr, l, mid, x << 1));
        if(mid < qr) ans = max(ans, query(ql, qr, mid + 1, r, x << 1 | 1));
        ans = min(ans, a[x]);
        return ans;
    }
}

using pii = pair<int, int>;
set<pii> s[N];

set<pii>::iterator split(set<pii> &s, int x)
{
    auto it = s.upper_bound({x, V + 1});
    if(it == s.begin()) return it;
    if((--it)->second < x) return ++it;
    pii y = *it;s.erase(it);
    if(x > y.first) s.insert({y.first, x - 1});
    return s.insert({max(y.first, x), y.second}).first;
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    int q;cin >> q;
    
    sgt::init();
    for(int i = 0; i <= V; i ++) s[i].insert({1, V});

    int ans = 0;
    while(q --)
    {
        int op;cin >> op;
        if(op == 1)
        {
            int x, a, b;cin >> x >> a >> b;
            x ^= ans, a ^= ans, b ^= ans;
            auto itb = split(s[x], b + 1);
            auto ita = split(s[x], a);
            for(auto it1 = ita; it1 != itb; it1 ++)
                sgt::update(it1->first, it1->second, 1, V, 1, 0, x);
            s[x].erase(ita, itb);
        }
        else
        {
            int l, r;cin >> l >> r;
            l ^= ans, r ^= ans;
            int aans = sgt::query(l, r, 1, V, 1);
            cout << aans << "\n";
            ans += aans;
        }
    }

    return 0;
}

标签:set,limits,int,max,Ans,CFgym103260K,ans,Painting,Rectangle
From: https://www.cnblogs.com/adam01/p/17649340.html

相关文章

  • plt.Rectangle((x0, y0), w, h)参数解释
    plt.Rectangle((x0,y0),w,h)中的(x0,y0)表示矩形的左上角坐标,而不是中心点或左下角坐标。这个函数用于在Matplotlib中绘制矩形,其中(x0,y0)是矩形的左上角的坐标,w是矩形的宽度,h是矩形的高度。如果你想要绘制一个以(x0,y0)为中心的矩形,你需要根据中心坐标计算出左......
  • 洛谷_[P4084]Barn Painting G题解
    题目链接这题我们可以定义一个二维的dp数组,在dp[i][j]中:i表示对于节点i,j有1,2,3三种状态,表示当点i选择被染成颜色j时,以i为根的这颗子树有多少种染色方法。那么根据乘法原理,节点i的方案数肯定等于i的每个儿子的方案数量之积。这道题整个挺简单的,剩下细节......
  • Painting the Fence 题解
    题目传送门一道枚举题。我们可以直接枚举那\(2\)个去掉的粉刷匠。先统计一下每个栅栏会被多少个粉刷匠刷到,然后枚举第一个被去掉的粉刷匠,然后计算剩下的粉刷匠会将每个栅栏刷到多少次,我们只需要看只能被刷\(1\)次的栅栏就行了。接着处理一个前缀和数组,记录前\(i\)个栅栏......
  • Educational Codeforces Round 152 (Rated for Div. 2) D. Array Painting
    初始所有点都是蓝色的,给定一个数组,每个元素为0,1,2等值,两种操作,选定一个点花1元变红,或者选定一个为1或者2的红色点,减去一个价值,让周围的点变红,最后所有点都要变红思路:贪心,对于一个数组来说我们找寻连续的不等于0的一段,判断每一段最多所能变红的存在两种情况010,这种情况花1可以最......
  • QML(二)-Item与Rectangle
    本文内容基于:QML教程-P2QML-Item与RectangleQt助手虽然我们可以在QtCreator中来搜索内容但是也可以通过Qt助手来查询,Qt助手的位置就在Qt安装目录中,当然需要根据自己的编译方式不同选择不同目录下的Qt助手,例如,我选择使用mingw8.1版本的64位进行编译,我的就在mingw81_64目录下。Recta......
  • 小米 Online Judge TCO 预选赛 Rectangle [离散化+二维前缀和]
    题目链接:https://code.mi.com/problem/list/view?id=151&cid=13 解题思路:首先将x轴和y轴坐标离散化,然后就可以用二维前缀和求得每个格子被覆盖了几次,然后就可以求出每个格子的贡献,最后将总的贡献和乘以总的方案数的逆元即可。#include<bits/stdc++.h>#definexfirst#define......
  • leetcode 836. Rectangle Overlap
    Arectangleis representedasa list[x1,y1,x2,y2],where (x1,y1) arethecoordinatesofitsbottom-leftcorner,and(x2, y2) arethecoordinatesofitstop-rightcorner.Tworectanglesoverlapiftheareaoftheirintersectionispositive. Tobecl......
  • AtCoder Regular Contest 119 D Grid Repainting 3
    洛谷传送门AtCoder传送门对每个红格的行和列连边,建出二分图。对于二分图中的每个连通块分别考虑。大胆猜测对于每个连通块,我们都能够进行适当的操作,使得只有一行/一列没被操作(显然不能使所有行和列都被操作)。对应的方案就是随便取一棵生成树,把不被染白的那一行/列拎出来当根,然......
  • Python元组传参, cv2.rectangle的奇怪错误
    colors=(np.array(colors)*255).astype(np.int)color=colors[i]cv2.rectangle(img,(x0,y0),(x1,y1),color,2)"""tuple(colors[i])(0,255,0)tuple(colors[i])==(0,255,0)Truecv2.rectangle(img,(x0,y0),(x1,y1),colors[i],2)Tra......
  • Counting Rectangles UVA - 10574
    给出n个点。问选出4个点作为定点,能够组成多少个平行与坐标轴的矩形。 点按照x排序 n^2挑选出垂直x轴的线段,按照y1排序  #include<iostream>#include<cstring>#include<algorithm>#include<vector>usingnamespacestd;constintN=1e5;structT{ intx......