zoukankan      html  css  js  c++  java
  • LOJ2736 回转寿司

    题目蓝链

    Solution

    直接分块就可以了,对于每一块维护一个大根堆

    每次操作对于整块的部分就直接先把待替换元素压进去,然后取出堆顶的元素

    对于边界块就直接利用一个小根堆去暴力重构,然后直接依次从堆中取出最小的元素去替换就可以了,然后直接重建这个块的大根堆

    时间复杂度(mathcal{O}(q cdot sqrt n cdot log(q + sqrt n)))

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define fst first
    #define snd second
    #define squ(x) ((LL)(x) * (x))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long LL;
    typedef pair<int, int> pii;
    
    inline int read() {
    	int sum = 0, fg = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
    	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    	return fg * sum;
    }
    
    const int maxn = 4e5 + 10;
    const int B = 577;
    
    priority_queue<int> pq[maxn / B + 5];
    int n, m, blks, a[maxn], S[maxn / B + 5][maxn], top[maxn / B + 5];
    
    int pos(int x) { return (x - 1) / B + 1; }
    
    void Set(int x) {
    	if (x <= 0 || x > blks) return;
    	priority_queue<int, vector<int>, greater<int> > now(S[x] + 1, S[x] + top[x] + 1);
    	int l = (x - 1) * B + 1, r = min(x * B, n);
    	for (int i = l; i <= r; i++) {
    		now.push(a[i]);
    		a[i] = now.top();
    		now.pop();
    	}
    	top[x] = 0;
    }
    
    int solve(int l, int r, int v) {
    	int x = pos(l), y = pos(r);
    	if ((l - 1) % B == 0) --x;
    	if (r % B == 0) ++y;
    	if (x == y) {
    		Set(x);
    		for (int i = l; i <= r; i++) if (a[i] > v) swap(a[i], v);
    		pq[x] = priority_queue<int>(a + (x - 1) * B + 1, a + x * B + 1);
    	} else {
    		Set(x), Set(y); int _l = x * B;
    		for (int i = l; i <= _l; i++) if (a[i] > v) swap(a[i], v);
    		pq[x] = priority_queue<int>(a + (x - 1) * B + 1, a + _l + 1);
    		++x, --y;
    		for (int i = x; i <= y; i++) {
    			if (pq[i].top() > v) {
    				pq[i].push(v);
    				S[i][++top[i]] = v;
    				v = pq[i].top();
    				pq[i].pop();
    			}
    		}
    		for (int i = y * B + 1; i <= r; i++) if (a[i] > v) swap(a[i], v);
    		pq[y + 1] = priority_queue<int>(a + y * B + 1, a + (y + 1) * B + 1);
    	}
    	return v;
    }
    
    int main() {
    	freopen("in.in", "r", stdin);
    	freopen("in.out", "w", stdout);
    
    	n = read(), m = read();
    	blks = (n - 1) / B + 1;
    
    	int cnt = 0;
    	for (int i = 1; i < blks; i++)
    		for (int j = 1; j <= B; j++)
    			pq[i].push(a[++cnt] = read());
    	for (int i = (blks - 1) * B + 1; i <= n; i++)
    		pq[blks].push(a[++cnt] = read());
    
    	while (m--) {
    		int l = read(), r = read(), v = read();
    		if (l <= r) printf("%d
    ", solve(l, r, v));
    		else printf("%d
    ", solve(1, r, solve(l, n, v)));
    	}
    
    	return 0;
    }
    

    Summary

    其实我在考试的时候已经无限接近正解了,但是在想怎么重构块的时候卡住了。我一开始以为最终序列和操作的顺序有关,所以没想到直接把所有的操作元素放到一个小根堆里就可以了

  • 相关阅读:
    Spring 09 : AOP实例
    Spring08 AOP概念
    Spring 07 : 动态代理
    Spring06 Spring+Junit
    Spring05 : 基于注解的IOC
    Spring03 : 依赖注入
    jupyter修改python核(使用不同的python虚拟环境)
    线性代数的本质——引入几何视角
    图像的去雾与加雾
    从MATLAB看一个IDE应该具有的素质
  • 原文地址:https://www.cnblogs.com/xunzhen/p/9844547.html
Copyright © 2011-2022 走看看