首页 > 其他分享 >[Ynoi2012] NOIP2015 充满了希望

[Ynoi2012] NOIP2015 充满了希望

时间:2024-10-04 22:02:01浏览次数:1  
标签:NOIP2015 return int Ynoi2012 充满 mid 查询 ask 操作

[Ynoi2012] NOIP2015 充满了希望

题意

给一个长为 \(n\) 的序列,有 \(m\) 个操作,操作编号从 \(1\) 到 \(m\),每个操作为:

1 x y:将序列位置为 \(x,y\) 的两个元素交换。

2 l r x:将序列区间 \([l,r]\) 内所有元素修改为 \(x\)。

3 x:查询序列 \(x\) 位置的值。

现在有 \(q\) 次查询,每次查询给出一个操作的区间 \([l,r]\):

先将序列中的元素全部置为 \(0\),之后依次进行从 \(l\) 到 \(r\) 的所有操作,求出所有这些操作中所有 \(3\) 操作的答案的和。

查询之间独立。

思路

套路一样

用线段树维护一个元素被哪一次的操作染色(操作的编号)。对询问离线,按 \(r\) 排序,对其做扫描线。

由于询问已经拍好序,考虑第 \(i\) 个询问的时候已经操作完了 \(1\sim r_i\) 的操作。我们只想要 \(l_i\sim r_i\) 之间操作贡献的答案,如何消除 \(1\sim l_i-1\) 的操作对答案的影响呢?

把每次的操作三查询出的答案以操作的时间为下标放到树状数组里,表示它会对之后的查询造成影响,那我们询问的时候就可以直接用树状数组区间查询统计答案。具体的,就是 bit.ask(r) - bit.ask(l-1)

大致思路就是这样,具体的操作也比较好实现。操作一是两个单点修改,操作二是区间覆盖。

代码

#include <bits/stdc++.h>

using namespace std;

using ubt = long long;

inline int read() {
    int s = 0, w = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-')
            w = -w;
        c = getchar();
    }
    while (isdigit(c)) {
        s = s * 10 + c - 48;
        c = getchar();
    }
    return s * w;
}

const int maxN = 1e6 + 7;

int n, m, Q;

struct BIT {
    ubt t[maxN];
    void add(int x, int v) {
        for (; x && x <= m; x += x & -x)
            t[x] += v;
    }
    ubt ask(int x) {
        ubt res = 0;
        for (; x > 0; x -= x & -x)
            res += t[x];
        return res;
    }
    ubt query(int x, int y) {
        return ask(y) - ask(x - 1);
    }
} bit;

struct Tree {
    int l, r;
    int v, lz;
} t[maxN << 2];
#define ls (p << 1)
#define rs (p << 1 | 1)
void make(int p, int lz) {
    t[p].lz = lz;
    t[p].v = lz;
}
void down(int p) {
    if (!t[p].lz) return;
    make(ls, t[p].lz);
    make(rs, t[p].lz);
    t[p].lz = 0;
}
void build(int L, int R, int p) {
    t[p].l = L, t[p].r = R;
    if (L == R) return;
    int mid = (L + R) >> 1;
    build(L, mid, ls), build(mid + 1, R, rs);
}
void change(int L, int R, int p, int v) {
    if (L <= t[p].l && t[p].r <= R)
        make(p, v);
    else {
        down(p);
        int mid = (t[p].l + t[p].r) >> 1;
        if (L <= mid)
            change(L, R, ls, v);
        if (R > mid)
            change(L, R, rs, v);
    }
}
int ask(int K, int p) {
    if (t[p].l == t[p].r)
        return t[p].v;
    down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    return K <= mid ? ask(K, ls) : ask(K, rs);
}
void Swap(int x, int y) {
    int resx = ask(x, 1);
    int resy = ask(y, 1);
    change(x, x, 1, resy);
    change(y, y, 1, resx);
}

struct modi {
    int op, x, y, k;
    int id;
} mo[maxN];

void modify(modi G) {
    if (G.op == 1)
        Swap(G.x, G.y);
    if (G.op == 2)
        change(G.x, G.y, 1, G.id);
    if (G.op == 3) {
        int t = ask(G.x, 1);
        bit.add(t, mo[t].k);
    }
}

struct ques {
    int l, r, id;
    friend bool operator < (ques A, ques B) {
        return A.r < B.r;
    }
} q[maxN];
ubt ans[maxN];

int main() {
    n = read(), m = read(), Q = read();
    build(1, n, 1);
    
    mo[0].k = 0;
    for (int i = 1; i <= m; i++) {
        mo[i].id = i;
        mo[i].op = read();
        mo[i].x = read();
        if (mo[i].op != 3) {
            mo[i].y = read();
            if (mo[i].op == 2)
                mo[i].k = read();
        }
    }

    for (int i = 1; i <= Q; i++)
        q[i].l = read(), q[i].r = read(), q[i].id = i;
    sort(q + 1, q + Q + 1);

    int now = 1;
    for (int nw = 1; nw <= Q; nw++) {
        int l = q[nw].l, r = q[nw].r;
        while (now <= m && now <= r)
            modify(mo[now++]);
        ans[q[nw].id] = bit.query(l, r);
    }

    for (int i = 1; i <= Q; i++)
        cout << ans[i] << '\n';
}

标签:NOIP2015,return,int,Ynoi2012,充满,mid,查询,ask,操作
From: https://www.cnblogs.com/ccxswl/p/18447380

相关文章

  • 【贪心】【二分】[NOIP2015]跳石头
    https://ac.nowcoder.com/acm/contest/22353/C正确的思路是二分查找+贪心。具体来说,可以通过二分来猜测一个最小的跳跃距离,然后通过贪心算法判断是否可以通过移除石头使所有的跳跃都满足这个最小跳跃距离。这种方法的核心是逐步逼近最优解,而不是直接删除前m小的元素。细节:在......
  • [NOIP2015 提高组] 子串
    算法状态定义最初显然可以想到\(f[i][j][k]\)表示\(A\)串前\(i\)个,\(B\)串前\(j\)个,分割了\(k\)个子串但是这样无法递推\(k\)维于是加上一位\(f[i][j][k][0/1]\),最后一维表示是否选择\(A\)子串当前这一位,也就可以递推的计算状态转移当前位置不使......
  • AI写作新体验:芝士AI,让每个字都充满智慧!
    在很多人还不会用或者想不到用AI的时候,居然有人成功地打破了信息壁垒,开始尝试用AI解决问题,因为AI可以用来生成论文大纲、润色美化论文、阅读查找参考文献……目前市面上AI写作工具可谓是百花齐放,但良莠不齐,真正专业的论文写作工具其实并不多。下面给大家推荐一个不错的写论文......
  • 信息学奥赛初赛天天练-81-NOIP2015普及组-完善程序-二分答案、二分查找、中位数、二分
    1完善程序(单选题,每小题3分,共30分)中位数median给定n(n为奇数且小于1000)个整数,整数的范围在0∼m(0<m<2^31)之间,请使用二分法求这n个整数的中位数。所谓中位数,是指将这n个数排序之后,排在正中间的数。(第五空2分,其余3分)01#include<iostream>02usingnamespace......
  • 信息学奥赛初赛天天练-80-NOIP2015普及组-基础题5-错位排列、二叉树、完全二叉树、叶
    NOIP2015普及组基础题521重新排列1234使得每一个数字都不在原来的位置上,一共有()种排法22一棵结点数为2015的二叉树最多有()个叶子结点2相关知识点1)错位排列考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就......
  • 洛谷 P2680 [NOIP2015 提高组] 运输计划
    洛谷P2680[NOIP2015提高组]运输计划题意给出一棵树和\(m\)条路径,可以选择一条边,把边权改为\(0\),求\(m\)条路经长度最大值的最小值。思路看到最大值最小,可以想到二分答案,答案具有单调性。考虑如何判定答案\(x\)是否可行。统计所有长度大于\(x\)的路径,统计它们共......
  • 信息学奥赛初赛天天练-78-NOIP2015普及组-基础题3-中断、计算机病毒、文件传输协议FTP
    NOIP2015普及组基础题38所谓的“中断”是指()A操作系统随意停止一个程序的运行B当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的过程C因停机而停止一个程序的运行D电脑死机9计算机病毒是()A通过计算机传播的危害人体健康的一种......
  • 信息学奥赛初赛天天练-77-NOIP2015普及组-基础题2-二进制、连通图、最小生成树、链表
    NOIP2015普及组基础题24在计算机内部用来传送、存贮、加工处理的数据或指令都是以()形式进行的A二进制码B八进制码C十进制码D智能拼音码5下列说法正确的是()ACPU的主要任务是执行数据运算和程序控制B存储器具有记忆能力,其中信息任何时候都不会......
  • 信息学奥赛初赛天天练-76-NOIP2015普及组-基础题1-计算机存储、硬件系统、操作系统、
    NOIP2016普及组基础题111MB等于()A10000字节B1024字节C1000×1000字节D1024×1024字节2在PC机中,PENTIUM(奔腾)、酷睿、赛扬等是指()A生产厂家名称B硬盘的型号CCPU的型号D显示器的型号3操作系统的作用是()A把源程序译成目......
  • 二维码耍出新花样,充满创意艺术——Artistic QR Generation API
    艺术二维码API的申请与运用艺术二维码,这一创意十足的技术产物,将二维码与迷人的背景图像相结合,形成了既实用又富有美感的艺术作品。它们不仅保持了传统二维码的信息功能,可以被智能设备快速扫描识别,更融入了艺术元素,极大地提升了视觉吸引力和品牌识别度。在某些情况下,这些......