--- 这里是 cjiaw 的小窝(●'◡'●) ---

正在玩命加载中......

洛谷__P1503 鬼子进村(树形数据结构)

题目链接:P1503 鬼子进村 - 洛谷


题目大意:

给定一个长为  的  序列 初始为全 

有三种操作,

  • 操作D:修改  为 
  • 操作R:撤回一次最近的修改,
  • 操作Q:给定  求第  个元素所在的全部是  的联通块的大小。

思路:

set 记录 1 的位置,

对于操作Q,就是找 set 中 第一个大于等于 x 的位置 - 第一个小于等于 x 的位置

对于操作R,用 stack 维护,弹出栈并在set中抹除掉 x


代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#include<array>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/numeric>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
#define pb push_back
#define gmap __gnu_pbds::gp_hash_table
#define power __gnu_cxx::power
using namespace std;
typedef pair<int, int> pii;

const int N = 200086, mod = 998244353;

int n, m;
stack<int> st;
set<int> s;

void solve() {

    cin >> n >> m;
    s.insert(0), s.insert(n + 1);//初始化边界
    
    while (m--) {
        char c;
        int x;
        cin >> c;
        if (c == 'D') {
            cin >> x;
            s.insert(x);
            st.push(x);
        } else if (c == 'Q') {
            cin >> x;
            auto it = s.lower_bound(x);
            if (*it == x) {
                cout << 0 << endl;
                continue;
            }
            int res = *it - *(--it);
            cout << res - 1 << endl;
        } else {
            int u = st.top();
            st.pop();
            s.erase(s.find(u));
        }
        
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    
    int T = 1;
// cin >> T;
    while (T--) solve();
    
    return 0;
}

 

posted @ 2025-11-25 19:51  wwjjw  阅读(9)  评论(0)    收藏  举报