CCPC 网络选拔 array

题意

给一个\(1\)到\(n\)的排列

现在有\(m\)个操作,每个操作是下面的一种:

  • \((1,pos)\),指把\(pos\)位上的数增加\(10,000,000\)
  • \((2,r,k)\),询问操作,你需要输出一个数满足下列三个条件
    1. 这个数不等于\(a_i(1\leq i \leq r)\)中的任意一个
    2. 这个数不小于\(k\)
    3. 是满足上两个条件的数中的最小的一个

\(T\leq 10,1\leq n \leq 10^5, 1\leq m \leq 10^5 ,1\leq k\leq n\)

本题强制在线


解法

考场上头铁,硬肝了\(4h\)

结考后\(20\)分钟调出来,\(1A...\)但想出来还是很高兴的

我们会发现每次给出的\(k\)都在\([1,n]\)范围内,那么我们操作二中输出的数最大也就是\(n+1\)

所以给\(pos\)位上的数加上\(10^7\)实际上相当于把这个数从排列中删除

我们主要看第二个操作

对于\(2,3\)两个条件,我们能够很快想到权值线段树维护

每次在权值线段树中查询\([k,n]\),在满足条件\(1\)的情况下尽量往左走即可

那么我们怎么判断是否满足条件\(1\)呢?

我们可以发现条件\(1\)是关于位置的限制,所以我们在权值线段树中存储各个元素的位置并维护其最大值

那么在查询时按照以下的顺序即可:

如果左子树的位置最大值\(\geq r\),证明左子树中一定有满足条件的数,向左子树查询

否则如果右子树的最大值\(\geq r\),向右子树查询

如果左右子树都没有,返回一个极大值

在所有查询结果中取一个最小值即可

对于删除操作,直接把其位置设为一个极大值,因为只要询问区间包含这个数,这个数必然是合法的


代码

没封装,有点丑。。。

#include <cstdio>

using namespace std;

const int N = 1e6 + 10;
const int add = 10000000;

int T, n, m, lstans;
int a[N], b[N], mx[N << 2];

inline int max(int x, int y) { return x > y ? x : y; }

inline int min(int x, int y) { return x < y ? x : y; }  

void build(int root, int l, int r) {
    if (l == r) {
        mx[root] = b[l];
        return;
    }
    int mid = l + r >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
    mx[root] = max(mx[root << 1], mx[root << 1 | 1]);
}

void change(int root, int l, int r, int x) {
    if (l == r) {
        mx[root] = 0x7fffffff;
        return;
    }
    int mid = l + r >> 1;
    if (x <= mid)
        change(root << 1, l, mid, x);
    if (x > mid)
        change(root << 1 | 1, mid + 1, r, x);
    mx[root] = max(mx[root << 1], mx[root << 1 | 1]);
}

int query(int root, int l, int r, int x, int y, int v) {
    if (r < x || l > y) return 0x7fffffff;
    if (l == r) return l;
    int res = 0x7fffffff, mid = l + r >> 1;
    if (mx[root << 1] > v)
        res = min(res, query(root << 1, l, mid, x, y, v));
    if (res == 0x7fffffff && mx[root << 1 | 1] > v)
        res = min(res, query(root << 1 | 1, mid + 1, r, x, y, v));
    return res;
}

int main() {

    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i)    scanf("%d", a + i);
        for (int i = 1; i <= n; ++i)    b[a[i]] = i;

        build(1, 1, n);

        lstans = 0;
        int op, t1, t2, t3;
        while (m--) {
            scanf("%d", &op);
            if (op == 1) {
                scanf("%d", &t1);
                t1 ^= lstans;
                change(1, 1, n, a[t1]);
            } else {
                scanf("%d%d", &t2, &t3);
                t2 ^= lstans, t3 ^= lstans;
                lstans = query(1, 1, n, t3, n, t2);
                if (lstans == 0x7fffffff)   lstans = n + 1;
                printf("%d\n", lstans);
            }
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/VeniVidiVici/p/11449358.html

时间: 2024-11-10 12:53:55

CCPC 网络选拔 array的相关文章

2019 CCPC 网络选拔 Kth-occurrence

题意 给出一个字符串,每次询问其一个子串\([S_l,S_r]\)在原串中第\(k\)次出现所在的位置(开头位置) 解法 题意很简洁,思路也很简洁 就是代码巨难打 总之这道题还是让我很大程度上加深了对于\(SAM\)的认识啦,还去学了一下线段树合并 首先,根据后缀自动机的性质我们能知道题目所要求的的实际上是 \([S_l,S_r]\)所代表串所在后缀自动机的结点\(endpos\)集合中的第\(k\)个数 求区间第\(k\)大?权值线段树上啦 我们知道,对于后缀自动机上的某个结点,其\(endp

hdu6153 A Secret CCPC网络赛 51nod 1277 KMP

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意: 给出两个字符串S1,S2,求S2的所有后缀在S1中出现的次数与其长度的乘积之和. 思路: CCPC网络赛题解: https://post.icpc-camp.org/d/714-ccpc-2017 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1277   是一样的 将s1,s2翻转,转化为求前缀在s1中出

树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

1 // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree 2 // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以走多次,问从每个点出发的最大获益 3 // 思路: 4 // dp[i]: 从i点出发回到i点的最大值 5 // d[i][0] 从i点出发不回来的最大值 6 // d[i][1] 从i点出发取最大值的下一个点 7 // d[i][2] 从i点出发取次大值 8 // dfs1处理出这四个 9

2016 CCPC 网络赛 B 高斯消元 C 树形dp(待补) G 状压dp+容斥(待补) H 计算几何

2016 CCPC 网络赛 A - A water problem 水题,但读题有个坑,输入数字长度很大.. B - Zhu and 772002 题意:给出n个数(给出的每个数的质因子最大不超过2000),选出多个数相乘得b.问有多少种选法让b 为完全平方数. tags:高斯消元,求异或方程组解的个数.   好题 每个数先素数分解开.  对于2000以内的每个素数p[i],这n个数有奇数个p[i]则系数为1,偶数个则系数为0,最后n个数的p[i]系数异或和都要为0才会使得最后的积为完全平方数.

2018 CCPC网络赛

2018 CCPC网络赛 Buy and Resell 题目描述:有一种物品,在\(n\)个地点的价格为\(a_i\),现在一次经过这\(n\)个地点,在每个地点可以买一个这样的物品,也可以卖出一个物品,问最终赚的钱的最大值. solution 用两个堆来维护,一个堆维护已经找到卖家的,一个堆维护还没找到卖家的. 对于第\(i\)个地点,在已经找到卖家的堆里找出卖的钱的最小值,如果最小值小于\(a_i\),则将卖家换成\(i\),然后将原来的卖家放到没找到卖家的那里:如果最小值对于\(a_i\)

hdoj6703 2019 CCPC网络选拔赛 1002 array

题意 description You are given an array a1,a2,...,an(?i∈[1,n],1≤ai≤n). Initially, each element of the array is **unique**. Moreover, there are m instructions. Each instruction is in one of the following two formats: 1. (1,pos),indicating to change the

iOS网络: 把Array和Dictionaries序列化成JSON对象

你想把 Array 和 dictionary 序列化成 JSON 对象.以方便在网络中传输或者保存到磁盘中. 方案: 使用 NSJSONSerialization 这个类的 dataWithJSONObject:options:error:方法来实现. 讨论: NSJSONSerialization 这个类的 dataWithJSONObject:options:error:方法可以对数组和字典进行序列化,这些数组和字典包含的值为:NSString.NSNumber.NSArray.NSDict

2016 ccpc 网络选拔赛 F. Robots

Robots Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 60    Accepted Submission(s): 13 Problem Description QXJ has N robots on the plane, the i-th is at (xi,yi), numbereded 1 to N. Every robot

hdu 6152 : Friend-Graph (2017 CCPC网络赛 1003)

题目链接 裸的结论题.百度 Ramsey定理.刚学过之后以为在哪也不会用到23333333333,没想到今天网络赛居然出了.顺利在题面更改前A掉~~~(我觉得要不是我开机慢+编译慢+中间暂时死机,我还能再早几分钟过掉它 #include<bits/stdc++.h> using namespace std; int g[8][8]; int n; void solve() { for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++) for