F - One Occurrence CodeForces - 1000F (线段树+离线处理)

Posted qieqiemin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了F - One Occurrence CodeForces - 1000F (线段树+离线处理)相关的知识,希望对你有一定的参考价值。

You are given an array aa consisting of nn integers, and qq queries to it. ii-th query is denoted by two integers lili and riri. For each query, you have to find any integer that occurs exactly once in the subarray of aa from index lili to index riri (a subarray is a contiguous subsegment of an array). For example, if a=[1,1,2,3,2,4]a=[1,1,2,3,2,4], then for query (li=2,ri=6)(li=2,ri=6) the subarray we are interested in is [1,2,3,2,4][1,2,3,2,4], and possible answers are 11, 33 and 44; for query (li=1,ri=2)(li=1,ri=2) the subarray we are interested in is [1,1][1,1], and there is no such element that occurs exactly once.

Can you answer all of the queries?

Input

The first line contains one integer nn (1≤n≤5?1051≤n≤5?105).

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤5?1051≤ai≤5?105).

The third line contains one integer qq (1≤q≤5?1051≤q≤5?105).

Then qq lines follow, ii-th line containing two integers lili and riri representing ii-th query (1≤li≤ri≤n1≤li≤ri≤n).

Output

Answer the queries as follows:

If there is no integer such that it occurs in the subarray from index lili to index ririexactly once, print 00. Otherwise print any such integer.

Example

Input

61 1 2 3 2 422 61 2

Output

40

题意:

给你一个含有n个数的数组和q个询问,每一个询问给你一个区间l和r,请你输出一个在数组l~r区间中只出现一次的数,如果没有就输出0.

思路:

首先把询问按照r进行升序排序,来离线解决此问题。

我们用线段树维护一个pair<int,int>

first 和second 分别代表 这个位置的数当前位置下标和他前一个出现这个数的下标。

然后去询问区间询问区间中first 的最小值,判断是否比其区间的l小,如果小于则说明区间这个数仅出现一次,它的上一次如果存在的话,是在l左边。

代码实现起来细节还是很多的,多看代码理解一下吧。

其他做法可以参考这个大佬的博客(3个做法):https://blog.csdn.net/lzc504603913/article/details/83310266

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) return b ? gcd(b, a % b) : a;
ll lcm(ll a, ll b) return a / gcd(a, b) * b;
ll powmod(ll a, ll b, ll MOD) ll ans = 1; while (b) if (b % 2)  ans = ans * a % MOD;  a = a * a % MOD; b /= 2; return ans;
inline void getInt(int *p);
const int maxn = 500010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE code * * STARTS HERE ***/
struct node 
    pii num;
    int l, r;
 segment_tree[maxn << 2];
void build(int rt, int l, int r)

    segment_tree[rt].l = l;
    segment_tree[rt].r = r;
    segment_tree[rt].num = mp(0, 0);
    if (l == r) 
        return ;
    
    int mid = (l + r) >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);

void pushup(int rt)

    segment_tree[rt].num = min(segment_tree[rt << 1].num, segment_tree[rt << 1 | 1].num);

void update(int rt, int pos, int pre)

    if (segment_tree[rt].l == segment_tree[rt].r && segment_tree[rt].l == pos) 
        segment_tree[rt].num.fi = pre;
        segment_tree[rt].num.se = pos;
     else 
        int mid = segment_tree[rt].l + segment_tree[rt].r >> 1;
        if (pos <= mid) 
            update(rt << 1, pos, pre);
         else 
            update(rt << 1 | 1, pos, pre);
        
        pushup(rt);
    

pii ask(int rt, int l, int r)

    if (segment_tree[rt].l >= l && segment_tree[rt].r <= r) 
        return segment_tree[rt].num;
    
    pii res;
    res.fi = inf;
    int mid = (segment_tree[rt].r + segment_tree[rt].l) >> 1;
    if (l <= mid) 
        res = min(res, ask(rt << 1, l, r));
    
    if (r > mid) 
        res = min(res, ask(rt << 1 | 1, l, r));
    
    return res;

int a[maxn];
struct aaaaa 
    int l;
    int r;
    int id;
 b[maxn];
bool cmp(aaaaa aa, aaaaa bb)

    if (aa.r == bb.r) 
        return aa.l < bb.l;
     else 
        return aa.r < bb.r;
    

int last[maxn];
int ans[maxn];
int main()

    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int n;
    gbtb;
    cin >> n;
    build(1, 1, n);
    repd(i, 1, n) 
        cin >> a[i];
    
    int q;
    cin >> q;
    repd(i, 1, q) 
        cin >> b[i].l >> b[i].r;
        b[i].id = i;
    
    sort(b + 1, b + 1 + q, cmp);
    int cur = 1;
    repd(i, 1, q) 
        for (; cur <= b[i].r; cur++) 
            if (last[a[cur]]) 
                update(1, last[a[cur]], inf);
            
            update(1, cur, last[a[cur]]);
            last[a[cur]] = cur;
        
        auto temp = ask(1, b[i].l, b[i].r);
        if (temp.fi < b[i].l) 
            ans[b[i].id] = a[temp.se];
        
    
    repd(i, 1, q) 
        printf("%d\n", ans[i] );
    
    return 0;


inline void getInt(int *p)

    char ch;
    do 
        ch = getchar();
     while (ch == ' ' || ch == '\n');
    if (ch == '-') 
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') 
            *p = *p * 10 - ch + '0';
        
     else 
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') 
            *p = *p * 10 + ch - '0';
        
    




以上是关于F - One Occurrence CodeForces - 1000F (线段树+离线处理)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 1000F One Occurrence 主席树|| 离线+线段树

CodeForces - 1000F One Occurrence (主席树)

CodeForces - 1000F One Occurrence (主席树)

One Occurrence 线段树离线维护最小值

CF1000F One Occurrence 主席树 线段树

Last Occurrence - Medium