1002 ( array )

1005在这里

题意:
给定一个 1... n 1...n 1...n的一个排列,有两种操作

  1. a i a_i ai加上 1000000 1000000 1000000
  2. 查询不存在于 a 1 , . . a r a_1,..a_r a1,..ar中的大于 k k k的最大值
    强制在线

分析
换一个方向,就是查询大于等于 k k k的第一个不在 a 1 , . . . a r a_1,...a_r a1,...ar的数
我们可以维护 1.. n , n + 1 1..n,n+1 1..n,n+1的位置,查询 [ k , n + 1 ] [k,n+1] [k,n+1]的第一个大于 r r r的,先查询左边,如果存在就返回即可。



#include <bits/stdc++.h>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define  FI first
#define  SE second
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<<endl<<"DEBUG"<<endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int    prime = 999983;
const int    INF = 0x7FFFFFFF;
const LL     INFF = 0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL     mod = 1e9 + 7;
LL qpow(LL a, LL b) {LL s = 1; while (b > 0) {if (b & 1)s = s * a % mod; a = a * a % mod; b >>= 1;} return s;}
LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}
int dr[2][4] = {1, -1, 0, 0, 0, 0, -1, 1};
typedef pair<int, int> P;
const int maxn = 1e5 + 10;

int a[maxn];
int n, m;
#define lson (o<<1)
#define rson (o<<1|1)
int tree[maxn << 2];
void pushup(int o) {
    tree[o] = max(tree[lson], tree[rson]);
}
void Build(int o, int l, int r) {
    if (l == r) {
        tree[o] = a[l];
        return ;
    }
    int mid = (l + r) >> 1;
    Build(lson, l, mid);
    Build(rson, mid + 1, r);
    pushup(o);
}
void update(int o, int l, int r, int x) {
    if (l == r) {
        tree[o] = n + 1;
        return ;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
        update(lson, l, mid, x);
    else
        update(rson, mid + 1, r, x);
    pushup(o);
}
int  query(int o, int l, int r, int L, int t) {
    // cout << l << " " << r << " " << L << " " << tree[o] << " " << t << endl;
    if (tree[o] <= t) return n + 1;
    if (l == r) {
        if (tree[o] > t) return l;
        else
            return n + 1;
    }
    int mid = (l + r) >> 1;
    int ans = n + 1;
    if (L <= mid) {
        ans = min(ans, query(lson, l, mid, L, t));
    }
    if (ans < n + 1) return ans;
    return query(rson, mid + 1, r, L, t);

}
int now[maxn];
namespace io {
const int L = 1 << 20 | 1;
char ibuf[L], *iS, *iT, c, obuf[L], *oS = obuf, *oT = obuf + L - 1, qu[55]; int f, qr;
#ifdef whzzt
#define gc() getchar()
#else
#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, L, stdin), iS == iT ? EOF : *iS ++) : *iS ++)
#endif
template <class I>
inline void gi (I &x) {
    for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
    for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
}
inline void flush () {
    fwrite (obuf, 1, oS - obuf, stdout);
}
inline void putc (char x) {
    *oS ++ = x;
    if (oS == oT) flush (), oS = obuf;
}
template <class I>
void print (I x) {
    if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
    while (x) qu[++ qr] = x % 10 + '0', x /= 10;
    while (qr) putc (qu[qr --]);
}
struct io_ff { ~io_ff() { flush(); } } _io_ff_;
}
using io :: gi;
using io :: putc;
using io :: print;
int main(void)
{
    // freopen("E.cpp", "r", stdin);
    int T;
    // cin >> T;
    gi(T);
    while (T--) {
        // scanf("%d%d", &n, &m);
        gi(n), gi(m);
        for (int i = 1; i <= n; ++i) {
            int t;
            // scanf("%d", &t);
            gi(t);
            now[i] = t;
            a[t] = i;
        }
        a[n + 1] = n + 1;
        Build(1, 1, n + 1);
        int ans = 0;
        while (m--) {
            int op, t1, t2;//, t3;
            // scanf("%d", &op);
            gi(op);
            if (op == 1) {
                // scanf("%d", &t1);
                gi(t1);
                t1 ^= ans;
                // cout << t1 << " " << now[t1] << endl;
                update(1, 1, n + 1, now[t1]);
            }
            else {
                // scanf("%d%d", &t1, &t2);
                gi(t1), gi(t2);
                int r = t1 ^ ans;
                int k = t2 ^ ans;
                printf("%d\n", ans = query(1, 1, n + 1, k, r));
            }
        }
    }



    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值