题目的意思是在[1,n]区间中执行两种操作:
操作一:给定区间[l,r],依次标记该区间的所有数,如果数字已经在之前的被标记了,则不重复标记
操作二:给定[1,n]中的一个数x,直接输出x是第几个被标记的;如果没有被标记过,直接输出0
显然最直接的操作是遍历[l,r]依次标记,但是肯定会超时。
原因在于将所有数都进行判断:如果没有被标记过,那么我就标记;如果被被标记过,我就跳过
如果能不再判断被标记过的数,而是直接依次标记[l,r]中没有被标记过的数,那么不会超时,因为每个数最多标记一次,所以总共的标记次数为n次
那么我们可以用set来模拟
set<int> se
*se.lower_bound(x)直接查找第一个大于等于x的数.
int l, r; cin >> l >> r;
int now = l;
while(1){
    int next = *se.lower_bound(now);
    if(next > r) break;
    else ans[next] = ++ idx, se.erase(next);
    now = next; 
}
不断标记[l,r]中未被标记过的数,并且不断删除刚才被标记的数(所以set里面的数全是没有被标记过的数,标记数字和删除被标记的数字同时发生)
总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;


signed main(){
    HelloWorld;
    
    int n, q; cin >> n >> q;
    set<int> se;
    for(int i = 1; i <= n + 1; i ++) se.insert(i);
    vector<int> ans(n + 10);
    int idx = 0;
    while(q --){
        int op; cin >> op;
        if(op == 1){
            int l, r; cin >> l >> r;
            int now = l;
            while(1){
                int next = *se.lower_bound(now);
                if(next > r) break;
                else ans[next] = ++ idx, se.erase(next);
                now = next; 
            }
        }
        else{
            int x; cin >> x;
            cout << ans[x] << endl;
        }
    }

    return 0;
}