• CF351D Jeff and Removing Periods


    CF351D Jeff and Removing Periods
    HH的项链 加强版本。
    容易发现,这肯定和一段区间内数的种类数有关,然后,因为第一次操作的时候不能重排数列,那么我们只用讨论第一次的情况:

    • 可以一次把这种数删完。
    • 不能一次把这种数删完。
      那么我们可以记录一个 (fa_{i}) 代表 (i) 前面只要跨过区间 ([fa_i, i]) 就不能一次把这种数删完的第一个点。
      可以发现有两种转移

    [fa_{i} = pre_{pre_{i}} [i - pre_{i} e pre_{i} - pre_{pre_{i}}] ]

    [fa_{i} = fa_{pre_{i}} [i - pre_{i} = pre_{i} - pre_{pre_{i}}] ]

    然后整俩树状数组一整就完了。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10;
    
    ll N, M, val[MAXN], nxt[MAXN], lst[MAXN], pre[MAXN], fa[MAXN], ans[MAXN];
    
    struct que {
        ll l, r, id;
        friend bool operator < (que a, que b) {return a.r < b.r;}
    } Q[MAXN];
    
    struct arr {
        ll C[MAXN];
    
        void add(ll x, ll v) {
        	if (!x) return;
            while (x <= N) {
                C[x] += v;
                x += (x & (-x));
            }
        }
        
        ll ask(ll x) {
            ll ret = 0;
            while (x) {
                ret += C[x];
                x -= (x & (-x));
            }
            return ret;
        }
    } t1, t2;
    
    int main() {
        scanf("%lld", &N);
        for (ll i = 1; i <= N; i++) {
            scanf("%lld", val+i);
            nxt[lst[val[i]]] = i;
            pre[i] = lst[val[i]];
            lst[val[i]] = i;
            if (i - pre[i] == pre[i] - pre[pre[i]]) fa[i] = fa[pre[i]];
            else fa[i] = pre[pre[i]];
        }
        scanf("%lld", &M);
        for (ll i = 1; i <= M; i++) 
            scanf("%lld%lld", &Q[i].l, &Q[i].r), Q[i].id = i;
        sort(Q+1, Q+M+1);
        ll now = 0;
        for (ll i = 1; i <= M; i++) {
            while (now < Q[i].r) {
                ++now;
                t1.add(now, 1);
                t1.add(pre[now], -1);
                t2.add(fa[now], 1);
                t2.add(fa[pre[now]], -1);
            }
            ll tem1 = t1.ask(Q[i].r) - t1.ask(Q[i].l - 1), tem2 = t2.ask(Q[i].r) - t2.ask(Q[i].l - 1);
            ans[Q[i].id] = tem1 + (tem1 == tem2);
        }
        for (ll i = 1; i <= M; i++) 
            printf("%lld
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    利用Github Actions自动保持 GitHub 提交状态常绿
    windows下搭建轻量级php代码审计环境
    jquery实现点击弹出对话框
    redis学习记录(1)Redis简介
    StatefulSet
    Pod
    Spark 写Hive指定动态分区
    我常用的git操作
    在C#中如何使用GetOpenFileName函数多选文件
    image matching challenge
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13792709.html
Copyright © 2020-2023  润新知