zoukankan      html  css  js  c++  java
  • 8.26 雇佣

    题意

    给一个长为(N)的数列(a[1]...a[N]),要求支持如下操作

    操作一:给出一个整数(B),询问该数列中所有大于等于(B)的数能组成多少个极大连续段

    操作二:将(pos)位上的数改为(val)


    解法

    考场上想出来了...但是由于树状数组没判插入(0)的情况,获得了爆零的好成绩

    我们可以定义两个相邻数形成的二元组是合法的,当且仅当它们都$geq B $

    可以发现极大连续段的个数就是所有(geq B)的数的个数减去所有合法二元组的个数

    这样我们可以开两个树状数组,分别维护这两个值

    维护第一个很显然的,把树状数组当成桶插入即可

    维护第二个,每次把一个二元组中的最小值插入树状数组即可。在查询时我们查询的是(geq B)的数的个数,可以发现一个二元组中的最小值都大于(B)的话,这个二元组中的两个数一定都大于(B)

    这样计算即可


    代码

    #include <cstdio>
    #include <cctype>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 4e5 + 10;
    
    int read();
    
    int n, q;
    
    int a[N], b[N];
    
    inline int max(int x, int y) {
    	return x > y ? x : y;	
    }
    
    inline int min(int x, int y) {
    	return x < y ? x : y;	
    }
    
    struct opt {
    	int op;
    	int x, y;	
    } s[N];
    
    struct BIT {
    	int c[N];
    	
    	void insert(int p, int v) {
    		if (!p)	return;
    		while (p <= b[0])	c[p] += v, p += p & -p;	
    	}
    	int query(int p) {
    		int res = 0;
    		while (p)	res += c[p], p -= p & -p;
    		return res;	
    	}
    } tot, nxt;
    
    void discre() {
    	sort(b + 1, b + b[0] + 1);
    	b[0] = unique(b + 1, b + b[0] + 1) - b - 1;
    	for (int i = 1; i <= n; ++i)	
    		a[i] = upper_bound(b + 1, b + b[0] + 1, a[i]) - b - 1;	
    }
    
    int main() {
    	
    	freopen("maid.in", "r", stdin);
    	freopen("maid.out", "w", stdout);
    	
    	n = read(), q = read();
    	for (int i = 1; i <= n; ++i)	a[i] = read();
    	for (int i = 1; i <= n; ++i)	b[++b[0]] = a[i];
    	
    	for (int i = 1; i <= q; ++i) {
    		s[i].op = read();
    		if (s[i].op == 1) {
    			s[i].x = read();
    			b[++b[0]] = s[i].x;
    		} else {
    			s[i].x = read(), s[i].y = read();
    			b[++b[0]] = s[i].y;	
    		}
    	}
    	
    	discre();
    	
    	for (int i = 1; i <= n; ++i)	tot.insert(a[i], 1);
    	for (int i = 1; i < n; ++i)		nxt.insert(min(a[i], a[i + 1]), 1);
    		
    	for (int i = 1; i <= q; ++i) {
    		if (s[i].op == 1) {
    			int val = upper_bound(b + 1, b + b[0] + 1, s[i].x) - b - 1;
    			printf("%d
    ", nxt.query(val - 1) - tot.query(val - 1) + 1);
    		} else {
    			int pos = s[i].x, val = upper_bound(b + 1, b + b[0] + 1, s[i].y) - b - 1;
    			tot.insert(a[pos], -1);
    			tot.insert(val, 1);
    			nxt.insert(min(a[pos - 1], a[pos]), -1);
    			nxt.insert(min(a[pos], a[pos + 1]), -1);
    			nxt.insert(min(a[pos - 1], val), 1);
    			nxt.insert(min(val, a[pos + 1]), 1);
    			a[pos] = val;
    		}
    	}
    	
    	return 0;
    }
    
    int read() {
    	int x = 0, c = getchar();
    	while (!isdigit(c))	c = getchar();
    	while (isdigit(c))	x = x * 10 + c - 48, c = getchar();
    	return x;
    }
    
  • 相关阅读:
    测试计划设计
    测试方案
    使用gulp构建自动化工作流
    ESLint--定制你的代码规则
    Node.js学习笔记(一):快速开始
    React-Native性能优化点
    ES6笔记(一):ES6所改良的javascript“缺陷”
    windows下React-native 环境搭建
    使用ssh连接gitHub
    javascript中的prototype和constructor
  • 原文地址:https://www.cnblogs.com/VeniVidiVici/p/11426043.html
Copyright © 2011-2022 走看看