zoukankan      html  css  js  c++  java
  • JZOJ 6840. 【2020.11.5提高组模拟】铲雪(线段树)

    JZOJ 6840. 【2020.11.5提高组模拟】铲雪

    题目大意

    • n ∗ m n*m nm的土地上,每次操作前积雪深度 + 1 +1 +1 q q q次操作,把某行或某列积雪清零,或询问两点间积雪深度不超过某个值的最短路。
    • n , m ≤ 1 0 6 n,mleq10^6 n,m106 q ≤ 3 ∗ 1 0 5 qleq 3*10^5 q3105

    题解

    • 这题整张图 n ∗ m n*m nm特别大,直接跑最短路显然不可行,但稍微推一推,发现这题和最短路完全没关系,由于这题操作的特殊性,所以时刻 i i i时两点 ( s , t ) (s,t) (s,t) ( x , y ) (x,y) (x,y)之间最短路只有如下几种情况:
    • 先令 S = ∣ s − x ∣ + ∣ t − y ∣ S=|s-x|+|t-y| S=sx+ty
    • 1、 [ s , x ] [s,x] [s,x]中每一行或 [ t , y ] [t,y] [t,y]中每一列可走,则最短路为 S S S
    • 2、第 s s s行及第 y y y列或第 t t t列及第 x x x行可走,则最短路为 S S S
    • 3、第 s s s行及第 x x x行可走, [ t , y ] [t,y] [t,y]中某一列可走,则最短路为 S S S,纵向同理;
    • 4、第 s s s行及第 x x x行可走,有 [ 1 , t ) [1,t) [1,t)中(或 ( y , m ] (y,m] (y,m]中)第 j j j列可走,则最短路为 S + 2 ( t − j ) S+2(t-j) S+2(tj)(或 S + 2 ( j − y ) S+2(j-y) S+2(jy)),纵向同理。
    • 为什么没有其它路径曲折的情况呢?
    • 简单的画图可以发现,如果路径更曲折的情况走的通,那么前几种情况中某种也能走的通,且路径会更短,所以其它的不需要考虑。
    • 直接对行和列分别开一棵线段树维护即可。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 1000010
    int lx[N], ly[N];
    struct {
    	struct {
    		int mx = 0, mi = 0; 	
    	}f[N * 4];
    	void ch(int v, int l, int r, int x, int c) {
    		if(l == r) f[v].mi = f[v].mx = c;
    		else {
    			int mid = (l + r) / 2;
    			if(x <= mid) ch(v * 2, l, mid, x, c); else ch(v * 2 + 1, mid + 1, r, x, c);
    			f[v].mi = min(f[v * 2].mi, f[v * 2 + 1].mi);
    			f[v].mx = max(f[v * 2].mx, f[v * 2 + 1].mx);
    		}
    	}
    	int fmi(int v, int l, int r, int x, int y) {
    		if(l == x && r == y) return f[v].mi;
    		int mid = (l + r) / 2;
    		if(y <= mid) return fmi(v * 2, l, mid, x, y);
    		if(x > mid) return fmi(v * 2 + 1, mid + 1, r, x, y);
    		return min(fmi(v * 2, l, mid, x, mid), fmi(v * 2 + 1, mid + 1, r, mid + 1, y));
    	}
    	int fmx(int v, int l, int r, int x, int y) {
    		if(l == x && r == y) return f[v].mx;
    		int mid = (l + r) / 2;
    		if(y <= mid) return fmx(v * 2, l, mid, x, y);
    		if(x > mid) return fmx(v * 2 + 1, mid + 1, r, x, y);
    		return max(fmx(v * 2, l, mid, x, mid), fmx(v * 2 + 1, mid + 1, r, mid + 1, y));
    	}
    	int gtl(int v, int l, int r, int x, int y, int c) {
    		if(l == r) {
    			if(f[v].mx >= c) return l;
    			return 1e9;
    		}
    		int mid = (l + r) / 2;
    		if(y <= mid) return gtl(v * 2, l, mid, x, y, c);
    		if(x > mid) return gtl(v * 2 + 1, mid + 1, r, x, y, c);
    		if(fmx(v * 2, l, mid, x, mid) >= c) return gtl(v * 2, l, mid, x, mid, c);
    		return gtl(v * 2 + 1, mid + 1, r, mid + 1, y, c);
    	}
    	int gtr(int v, int l, int r, int x, int y, int c) {
    		if(l == r) {
    			if(f[v].mx >= c) return l;
    			return -1e9;
    		}
    		int mid = (l + r) / 2;
    		if(y <= mid) return gtr(v * 2, l, mid, x, y, c);
    		if(x > mid) return gtr(v * 2 + 1, mid + 1, r, x, y, c);
    		if(fmx(v * 2 + 1, mid + 1, r, mid + 1, y) >= c) return gtr(v * 2 + 1, mid + 1, r, mid + 1, y, c);
    		return gtr(v * 2, l, mid, x, mid, c);
    	}
    }a, b;
    int main() {
    	int n, m, Q, op, s, t, x, y, i, k;
    	scanf("%d%d%d", &n, &m, &Q); 
    	for(i = 1; i <= Q; i++) {
    		scanf("%d", &op);
    		if(op == 1) {
    			scanf("%d", &x);
    			a.ch(1, 1, n, x, i);
    			lx[x] = i;
    		}
    		else if(op == 2) {
    			scanf("%d", &x);
    			b.ch(1, 1, m, x, i);
    			ly[x] = i;
    		}
    		else if(op == 3) {
    			scanf("%d%d%d%d%d", &s, &t, &x, &y, &k);
    			if(i - max(lx[s], ly[t]) > k || i - max(lx[x], ly[y]) > k) {
    				printf("-1
    ");
    				continue;
    			}
    			int sum = abs(s - x) + abs(t - y);
    			if(i - lx[s] <= k && i - ly[y] <= k) {
    				printf("%d
    ", sum);
    				continue;
    			}
    			if(i - ly[t] <= k && i - lx[x] <= k) {
    				printf("%d
    ", sum);
    				continue;
    			}
    			if(i - a.fmi(1, 1, n, min(s, x), max(s, x)) <= k || i - b.fmi(1, 1, m, min(t, y), max(t, y)) <= k) {
    				printf("%d
    ", sum);
    				continue;
    			}
    			int ans = 1e9;
    			if(i - lx[s] <= k && i - lx[x] <= k) {
    				if(i - b.fmx(1, 1, m, min(t, y), max(t, y)) <= k) {
    					printf("%d
    ", sum);
    					continue;
    				}
    				int s0 = -1e9, s1 = 1e9;
    				if(min(t, y) > 1) s0 = b.gtr(1, 1, m, 1, min(t, y) - 1, i - k);
    				if(max(t, y) < m) s1 = b.gtl(1, 1, m, max(t, y) + 1, m, i - k);
    				ans = min(ans, sum + 2 * (min(t, y) - s0));
    				ans = min(ans, sum + 2 * (s1 - max(t, y)));
    			}
    			if(i - ly[t] <= k && i - ly[y] <= k) {
    				if(i - a.fmx(1, 1, n, min(s, x), max(s, x)) <= k) {
    					printf("%d
    ", sum);
    					continue;
    				}
    				int s0 = -1e9, s1 = 1e9;
    				if(min(s, x) > 1) s0 = a.gtr(1, 1, n, 1, min(s, x) - 1, i - k);
    				if(max(s, x) < n) s1 = a.gtl(1, 1, n, max(s, x) + 1, n, i - k);
    				ans = min(ans, sum + 2 * (min(s, x) - s0));
    				ans = min(ans, sum + 2 * (s1 - max(s, x)));
    			}
    			if(ans == 1e9) ans = -1;
    			printf("%d
    ", ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Magento 安装时文件权限 设置
    进度十(10.28)
    进度九(10.27)
    进度八(10.26)
    进度六(10.24)
    进度五(10.23)
    进度四(10.22)
    进度三(10.21)
    进度二(10.20)
    进度一(10.19)
  • 原文地址:https://www.cnblogs.com/LZA119/p/14279513.html
Copyright © 2011-2022 走看看