• [CF551E]GukiZ and GukiZiana


    题目大意:一个长度为$n(nleqslant5 imes10^5)$的数组,有两个操作:

    1. $1;l;r;x:$把区间$[l,r]$加上$x$
    2. $2;x:$询问$x$第一次出现和最后一次出现之间的距离,若没出现输出$-1$

    题解:分块,把每个块排个序(可以把数值为第一关键字,位置为第二关键字),整块的加就块上打$tag$,非整块的就暴力重构,查询就在每个块内求这个数出现位置,直接二分查找就行了。设块大小为$S$,修改复杂度$O(dfrac n S+2S)$,查询复杂度$O(dfrac n Slog_2 S)$,$S$略大于$sqrt n$最好。

    卡点:

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    namespace IO {
    	struct istream {
    #define M (1 << 24 | 3)
    		char buf[M], *ch = buf - 1;
    		inline istream() {
    #ifndef ONLINE_JUDGE
    			freopen("input.txt", "r", stdin);
    #endif
    			fread(buf, 1, M, stdin);
    		}
    		inline istream& operator >> (int &x) {
    			while (isspace(*++ch));
    			for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
    			return *this;
    		}
    		inline istream& operator >> (long long &x) {
    			while (isspace(*++ch));
    			for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
    			return *this;
    		}
    #undef M
    	} cin;
    	struct ostream {
    #define M (1 << 24 | 3)
    		char buf[M], *ch = buf - 1;
    		int w;
    		inline ostream& operator << (int x) {
    			if (!x) {
    				*++ch = '0';
    				return *this;
    			}
    			if (x < 0) *++ch = '-', x = -x;
    			for (w = 1; w <= x; w *= 10);
    			for (w /= 10; w; w /= 10) *++ch = (x / w) ^ 48, x %= w;
    			return *this;
    		}
    		inline ostream& operator << (const char x) {*++ch = x; return *this;}
    		inline ~ostream() {
    #ifndef ONLINE_JUDGE
    			freopen("output.txt", "w", stdout);
    #endif
    			fwrite(buf, 1, ch - buf + 1, stdout);
    		}
    #undef M
    	} cout;
    }
    
    #define maxn 500010
    const int BSZ = 1 << 10, BNUM = maxn / BSZ + 10;
    
    int bel[maxn];
    int L[BNUM], R[BNUM];
    long long tg[BNUM];
    struct node {
    	long long s;
    	int id;
    	inline node() {}
    	inline node(long long __s, int __id) : s(__s), id(__id) {}
    	inline node(int __s, int __id) {s = __s, id = __id;}
    	inline friend bool operator < (const node &lhs, const node &rhs) {
    		return lhs.s == rhs.s ? lhs.id < rhs.id : lhs.s < rhs.s;
    	}
    } s[maxn];
    
    int n, m, Bnum;
    
    int query(const int x) {
    	int max = 0, min = 0;
    	for (int i = 1; i <= Bnum; i++) if (tg[i] <= x) {
    		const int y = x - tg[i];
    		int l = std::lower_bound(s + L[i], s + R[i], node(y, 0)) - s;
    		if (l != R[i] && s[l].s == y) {
    			int r = std::lower_bound(s + L[i], s + R[i], node(y + 1, 0)) - s - 1;
    			if (!min) min = s[l].id;
    			max = s[r].id;
    		}
    	}
    	if (!min) return -1;
    	return max - min;
    }
    int main() {
    	IO::cin >> n >> m;
    	for (int i = 1; i <= n; i++) {
    		IO::cin >> s[i].s; s[i].id = i;
    		bel[i] = (i - 1 >> 10) + 1;
    	}
    
    	Bnum = bel[n];
    	for (int i = 1; i <= Bnum; i++) {
    		L[i] = i - 1 << 10, R[i] = L[i] + BSZ;
    	}
    	L[1] = 1, R[Bnum] = n + 1;
    	for (int i = 1; i <= Bnum; i++) {
    		std::sort(s + L[i], s + R[i]);
    	}
    
    	while (m --> 0) {
    		int op, l, r, x;
    		IO::cin >> op >> l;
    		if (op == 1) {
    			IO::cin >> r >> x;
    			const int lb = bel[l], rb = bel[r];
    			if (lb == rb) {
    				for (register node *now = s + L[lb]; now != s + R[lb]; ++now) if (l <= now -> id && now -> id <= r) now -> s += x;
    				std::sort(s + L[lb], s + R[lb]);
    			} else {
    				for (register node *now = s + L[lb]; now != s + R[lb]; ++now) if (l <= now -> id) now -> s += x;
    				std::sort(s + L[lb], s + R[lb]);
    				for (int i = lb + 1; i < rb; i++) tg[i] += x;
    				for (register node *now = s + L[rb]; now != s + R[rb]; ++now) if (now -> id <= r) now -> s += x;
    				std::sort(s + L[rb], s + R[rb]);
    			}
    		} else {
    			IO::cout << query(l) << '
    ';
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    JAVA-初步认识-常用对象API(集合框架-重点方法keyset演示图解)
    JAVA-初步认识-常用对象API(集合框架-常用方法演示)
    JAVA-初步认识-常用对象API(集合框架-Map集合特点常用方法)
    JAVA-初步认识-常用对象API(集合框架-练习-字符串长度排序)
    JAVA-初步认识-常用对象API(集合框架-treeset集合-二叉树)
    JAVA-初步认识-常用对象API(集合框架-treeset集合-Comparator比较器)9
    JAVA-初步认识-常用对象API(集合框架-treeset集合)
    JAVA-初步认识-常用对象API(集合框架-LinkedHashset集合)
    Spring整合hibernate的一个例子:用事务买书
    Spring整合hibernate的一个例子:用事务买书
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10135735.html
Copyright © 2020-2023  润新知