UOJ #515. 【UR #19】前进四 吉司机线段树

传送门

每个点若是能造成贡献,必然是从当前节点开始往后走的唯一最小值,所以考虑离线倒着做,吉司机线段树维护时间,取min成功就加1。

#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <stack>
#include <queue>
#include <numeric>
#include <cassert>
#include <bitset>
#include <cstdio>
#include <vector>
#include <unordered_set>
#include <cmath>
#include <map>
#include <unordered_map>
#include <set>
#include <deque>
#include <tuple>
 
#define all(a) a.begin(), a.end()
#define cnt0(x) __builtin_ctz(x)
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define cntone(x) __builtin_popcount(x)
#define db double
#define fs first
#define se second
#define AC main(void)
#define ls(u) u << 1
#define rs(u) u << 1 | 1
#define lc u << 1
#define rc u << 1 | 1
#define HYS std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
const long double eps = 1e-9;
int MOD = 571373;
const int LO = 1 << 20 | 1;
char buffer[LO],*S,*TT;
#define getchar() ((S==TT&&(TT=(S=buffer)+fread(buffer,1,LO,stdin),S==TT))?EOF:*S++)

namespace Fio {
    inline std::string sread() {
        std::string s = " ";
        char e = getchar();
        while (!isdigit(e) && !isalpha(e) && e != '*') e = getchar();
        while (isdigit(e) || isalpha(e) || e == '*') s += e, e = getchar();
        return s;
    }
    
    inline int read() {
        int x = 0, y = 1;
        char c = getchar();
        while (!isdigit(c)) {
            if (c == '-') y = -1;
            c = getchar();
        }
        while (isdigit(c)) {
            x = (x << 3) + (x << 1) + (c ^ 48);
            c = getchar();
        }
        return x *= y;
    }
    
    inline ll readll() {
        ll x = 0, y = 1;
        char c = getchar();
        while (!isdigit(c)) {
            if (c == '-') y = -1;
            c = getchar();
        }
        while (isdigit(c)) {
            x = (x << 3) + (x << 1) + (c ^ 48);
            c = getchar();
        }
        return x *= y;
    }
    inline void write(ll x) {
        if (x < 0) x = -x, putchar('-');
        ll sta[35], top = 0;
        do sta[top++] = x % 10, x /= 10;
        while (x);
        while (top) putchar(sta[--top] + '0');
        putchar('\n');
    }
    
    inline void write(int x) {
        if (x < 0) x = -x, putchar('-');
        int sta[35], top = 0;
        do sta[top++] = x % 10, x /= 10;
        while (x);
        while (top) putchar(sta[--top] + '0');
        putchar('\n');
    }
} using namespace Fio;

const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;

int min(int a, int b)	{return a > b ? b : a;}
int max(int a, int b)	{return a > b ? a : b;}

int n , m, _;

int d1[] = {0, 0, 1, -1};
int d2[] = {1, -1, 0, 0};

struct Node{
	int l, r;
	int mx, mx2, cnt;
	int tag = -1;
}tr[N << 2];

inline void pushup(int u){
	if(tr[lc].mx == tr[rc].mx){
		tr[u].mx = tr[rc].mx;
		tr[u].mx2 = max(tr[lc].mx2, tr[rc].mx2);
	}else if(tr[lc].mx > tr[rc].mx){
		tr[u].mx = tr[lc].mx;
		tr[u].mx2 = max(tr[lc].mx2, tr[rc].mx);
	}else{
		tr[u].mx = tr[rc].mx;
		tr[u].mx2 = max(tr[rc].mx2, tr[lc].mx);
	}
}

inline void build(int u, int l, int r){
	tr[u] = {l, r};
	tr[u].tag = -1;
	if(l == r){
		tr[u].mx = INF;
		tr[u].mx2 = -INF;
		return ;
	}
	
	int mid = l + r >> 1;
	build(lc, l, mid);
	build(rc, mid + 1, r);
	pushup(u);
}

inline void pushdown(int u){
	if(tr[u].mx < tr[lc].mx){
		tr[lc].mx = tr[u].mx;
		tr[lc].cnt += tr[u].cnt;
	}
	if(tr[u].mx < tr[rc].mx){
		tr[rc].mx = tr[u].mx;
		tr[rc].cnt += tr[u].cnt;
	}
	tr[u].cnt = 0;
}

inline void modify(int u, int l, int r, int x){
	if(tr[u].mx <= x)	return ;
	if(tr[u].l >= l && tr[u].r <= r && tr[u].mx2 < x){
		tr[u].mx = x;
		tr[u].cnt ++;
		return ;
	}
	
	pushdown(u);
	int mid = tr[lc].r;
	if(l <= mid)	modify(u << 1, l, r, x);
	if(r > mid)	modify(u << 1 | 1, l, r, x);
	pushup(u);
}

inline int query(int u, int x){
	if(tr[u].l == tr[u].r)	return tr[u].cnt;
	
	pushdown(u);
	int mid = tr[u].l + tr[u].r >> 1;
	if(x <= mid)	return query(u << 1, x);
	return query(u << 1 | 1, x);
}


struct node{
	int tm, v;
	int nxt;
}a[N << 1];

int last[N << 1], pre[N << 1], ans[N];

inline void solve(){
	n = read(), m = read();
	
	for(int i = 1; i <= n; i ++){
		int x = read();
		a[i] = node{0, x, 0};
		last[i] = i;
	}
	
	int cnt = 0;
	for(int i = 1; i <= m; i ++){
		int op = read();
		if(op == 1){
			int x = read(), v = read();
			a[last[x]].nxt = i + n;
			last[x] = i + n;
			a[i + n] = {i, v, 0};
		}else{
			int x = read();
			a[i + n] = {i, ++cnt, pre[x]};
			pre[x] = i + n;	
		}
	}
	
	build(1, 0, m);
	
	for(int i = n; i; i --){
		for(int j = i; j; j = a[j].nxt)
			modify(1, a[j].tm, (a[j].nxt ? a[a[j].nxt].tm - 1 : m), a[j].v);

		for(int j = pre[i]; j; j = a[j].nxt)
			ans[a[j].v] = query(1, a[j].tm);
	}

	for(int i = 1; i <= cnt; i ++)	write(ans[i]);
}


int main(){

	_ = 1;
  	//_ = read();
	while(_ --)
    	solve();

    return 0;
}
posted @ 2023-03-26 10:36  春始于雪之下  阅读(27)  评论(0编辑  收藏  举报