首页 > 其他分享 >「解题报告」AGC001F Wide Swap

「解题报告」AGC001F Wide Swap

时间:2023-04-15 11:22:06浏览次数:38  
标签:Wide int mid mn AGC001F st que Swap MAXN

首先题目给的限制条件很奇怪,下标差 \(K\) 而值域差 \(1\)。我们变成逆排列,然后就转换成了下标差 \(1\),值域差 \(K\) 了,每次操作就相当于交换相邻的两个差 \(\ge K\) 的数。

假设新的逆排列为 \(Q_i\)。我们发现,假如存在两个数差 \(<K\),那么它们的相对位置关系一定不变。那么我们现在有若干个限制 \((i, j)\),满足 \(Q_i\) 一定在 \(Q_j\) 前。那么我们可以将这个限制建出一个图,然后跑拓扑排序,便得到了一个可能的 \(Q_i\) 序列。

我们要求 \(P_i\) 字典序最小,这意味着 \(Q_i\) 中较小的数要尽可能靠前。那么最后一个数肯定尽可能大,让较小的数靠前。那么我们实际上就是要求 \(Q_i\) 翻转过来的字典序最大。那么我们只需要建反图,然后跑拓扑排序,每次选编号最大的点即可。

但是边数很多,直接跑显然不可行。我们可以拿线段树维护每个点的度数,然后维护一个最小值,每次删去一个数 \(i\),入度会减少 \(1\) 的点的区间为 \((i - K, i + K)\),然后找入度为 \(0\) 的点即可。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 500005;
int n, k, p[MAXN], q[MAXN];
struct SegmentTree {
    struct Node {
        pair<int, int> mn;
        int tag;
    } t[MAXN << 2];
#define lc (i << 1)
#define rc (i << 1 | 1)
    void pushDown(int i) {
        if (t[i].tag) {
            t[lc].mn.first += t[i].tag, t[lc].tag += t[i].tag;
            t[rc].mn.first += t[i].tag, t[rc].tag += t[i].tag;
            t[i].tag = 0;
        }
    }
    void build(int i = 1, int l = 1, int r = n) {
        t[i].mn = { 0, l };
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(lc, l, mid), build(rc, mid + 1, r);
    }
    void update(int d, int v, int i = 1, int l = 1, int r = n) {
        if (l == r) {
            t[i].mn.first = v;
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(i);
        if (d <= mid) update(d, v, lc, l, mid);
        else update(d, v, rc, mid + 1, r);
        t[i].mn = min(t[lc].mn, t[rc].mn);
    }
    void add(int a, int b, int v, int i = 1, int l = 1, int r = n) {
        if (a <= l && r <= b) {
            t[i].mn.first += v, t[i].tag += v;
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(i);
        if (a <= mid) add(a, b, v, lc, l, mid);
        if (b > mid) add(a, b, v, rc, mid + 1, r);
        t[i].mn = min(t[lc].mn, t[rc].mn);
    }
} st;
struct BinaryIndexTree {
    int a[MAXN];
#define lowbit(x) (x & (-x))
    void add(int d, int v) {
        while (d <= n) {
            a[d] += v;
            d += lowbit(d);
        }
    }
    int query(int d) {
        if (!d) return 0;
        int ans = 0;
        while (d) {
            ans += a[d];
            d -= lowbit(d);
        }
        return ans;
    }
    int query(int l, int r) {
        return query(r) - query(l - 1);
    }
} bit;
int ans[MAXN], m;
int ans2[MAXN];
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &p[i]);
        q[p[i]] = i;
    }
    st.build();
    priority_queue<int> que;
    for (int i = n; i >= 1; i--) {
        int ind = bit.query(max(q[i] - k + 1, 1), min(q[i] + k - 1, n));
        if (!ind) {
            que.push(q[i]);
            st.update(q[i], INT_MAX);
        } else {
            st.update(q[i], ind);
        }
        bit.add(q[i], 1);
    }
    while (!que.empty()) {
        int u = que.top(); que.pop();
        ans[++m] = u;
        st.add(max(1, u - k + 1), min(u + k - 1, n), -1);
        while (st.t[1].mn.first == 0) {
            int v = st.t[1].mn.second;
            que.push(v);
            st.update(v, INT_MAX);
        }
    }
    for (int i = 1; i <= n; i++) {
        ans2[ans[n - i + 1]] = i;
    }
    for (int i = 1; i <= n; i++) {
        printf("%d\n", ans2[i]);
    }
    return 0;
}

标签:Wide,int,mid,mn,AGC001F,st,que,Swap,MAXN
From: https://www.cnblogs.com/apjifengc/p/17320745.html

相关文章

  • faceswap个人小白安装详细
    前言:之前看了几个视频挺好玩的单纯想安装玩玩环境:win10_64,intelCPU,NVIDIAGPU·本文章参考以及部分搬运知乎博主:小虎AI珏爷,原文地址:AI换脸:faceswap操作教程-知乎(zhihu.com) 开始操作:1、下载安装最新的Python3Anaconda:https://www.anaconda.com/downloa......
  • [AGC001F] Wide Swap
    考虑转化对所有能操作得到的\(P\)集合的判定。求\(P\)的逆置换\(Q\)(交换下标和值),操作转化为:若\(|Q_i-Q_{i+1}|\geK\),可交换\(i\)和\(i+1\)。这样转化交换的就是相邻两个位置的值,如果没有前面的限制,任何排列都可以被操作得到。加上限制,显然有必要条件:数值对\((u,v)\)的位置大小......
  • Linux系统之armbain配置swap交换分区
    (Linux系统之armbain配置swap交换分区)一、检查本地环境1.检查系统版本#cat/etc/os-releaseNAME="Ubuntu"VERSION="20.04.2LTS(FocalFossa)"ID=ubuntuID_LIKE=debianPRETTY_NAME="Ubuntu20.04.2LTS"VERSION_ID="20.04"HOME_URL="https......
  • D. A Wide, Wide Graph
    D.AWide,WideGraphYouaregivenatree(aconnectedgraphwithoutcycles)with$n$vertices.Considerafixedinteger$k$.Then,thegraph$G_k$isanundirectedgraphwith$n$vertices,whereanedgebetweenvertices$u$and$v$existsifandonlyif......
  • Linux 扩容swap交换分区
    ddif=/dev/zeroof=swapfilebs=100Mcount=50这条命令从硬盘里分出一个100M×50=5G大小的空间,挂在swapfile上注意:这里我们bs(buffsize)给的100M,bs大小可以根据free-h命令查看的buff/cache的大小来决定,如果给大了可能会报dd:memoryexhaustedbyinputbufferofsize......
  • Ubuntu 17.04 将取消 Swap 分区?
    Canonical的软件工程师DimitriJohnLedkov最近宣布即将发布的Ubuntu Linux 系统安装时将丢弃Swap分区方式,改为交换文件方式。对我们中的大多数使用带SSD或NVMe闪盘及内存充足的人来说,这不是什么大新闻。不过那些想要将Ubuntu后续版本安装在10多年前PC......
  • Ubuntu 17.04 将取消 Swap 分区?
    Canonical的软件工程师DimitriJohnLedkov最近宣布即将发布的Ubuntu Linux 系统安装时将丢弃Swap分区方式,改为交换文件方式。对我们中的大多数使用带SSD或NVMe闪盘及内存充足的人来说,这不是什么大新闻。不过那些想要将Ubuntu后续版本安装在10多年前PC......
  • [ Linux ] swap 分区优化
    https://www.cnblogs.com/yeungchie/swappinessThiscontrolisusedtodefinehowaggressivethekernelwillswapmemorypages.Highervalueswillincreaseagg......
  • swap交换空间设置及清空缓存的命令:
    linuxswap空间的swappiness=0 linux会使用硬盘的一部分做为SWAP分区,用来进行进程调度--进程是正在运行的程序--把当前不用的进程调成‘等待(standby)‘,甚至‘睡眠(slee......
  • 增加linux的swap内存
    1.创建swap分区的文件ddif=/dev/zeroof=swapfilebs=1Mcount=1024其中bs是每块的大小,count是块的数量;bscount,就是swap文件的大小:这里1M1024=1G。可以根据需要自行调整......