zoukankan      html  css  js  c++  java
  • codechef

    Graph on a Table

    题意

    有一张 $ n imes m $ 的网格图,每次可以从 $ (x_0, y_0) $ 跳到 $ (x_1, y_1) $ 当且仅当 $ x_0 < x_1 $ 且 $ y_0 < y_1 $ ,同时这两个点都要在同一个给出的矩形中,求最多可以经过多少个网格并求出方案数对 $ 10^9 + 7 $ 取模。

    做法

    由于要求的是最长路经,所以对于路径相邻的两个位置 $ (x_i, y_i) $ 和 $ (x_{i + 1}, y_{i + 1}) $ 满足 $ x_i + 1 = x_{i + 1} $ 或 $ y_i + 1 = y_{i + 1} $ 。
    考虑DP,预处理出每个点可以从那些地方转移( $ Left[i][j] $ 和 $ Up[i][j] $ 分别维护这个点可以转移的最左和最上方的位置 )。
    然后单调队列优化DP即可。

    #include <bits/stdc++.h>
    #define mp make_pair
    #define fst first
    #define snd second
    #define rep(i, a, b) for(int i = (a), i##ed = (b); i <= i##ed; i++)
    #define per(i, a, b) for(int i = (a), i##ed = (b); i >= i##ed; i--)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int mod = 1e9 + 7;
    const int N = 2010, M = 500010;
    
    inline void file() {
    	freopen("roche.in", "r", stdin);
    	freopen("roche.out", "w", stdout);
    }
    inline int Max(int x, int y) { return x > y ? x : y; }
    inline int Min(int x, int y) { return x < y ? x : y; }
    void gi(int &x) {
    	x= 0; register char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar());
    	for(; c >= '0' && c <= '9';)
    		x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    }
    
    int T, n, m, q;
    struct P {
    	int x, y, xx, yy;
    	inline bool operator<(const P &yy)const { return x < yy.x; }
    }; P a[M];
    int up[N][N], lt[N][N];
    struct Node {
    	int len, s; Node(int X = 0, int Y = 0) : len(X), s(Y) {}
    	inline bool operator<(const Node &yy)const { return len < yy.len; }
    }; Node ans, f[N][N];
    struct Queue {
    	Node a[N]; int f, e, s[N], id[N];
    	void init(int x) { f = 1, e = 0; rep(i, 1, x) s[i] = 0; }
    	void push(int x, Node w) {
    		for(; f <= e && a[e] < w;)
    			s[a[e].len] = (s[a[e].len] - a[e].s + mod) % mod, --e;
    		s[w.len] = (s[w.len] + w.s) % mod, a[++e] = w, id[e] = x;
    	}
    	Node ask(int x) {
    		for(; f <= e && id[f] < x;)
    			s[a[f].len] = (s[a[f].len] - a[f].s + mod) % mod, ++f;
    		return Node(a[f].len + 1, s[a[f].len]);
    	}
    }; Queue Up[N], Lt[N];
    
    inline Node operator+(Node x, Node y) {
    	if(x.len ^ y.len) return x.len > y.len ? x : y;
    	return Node(x.len, (x.s + y.s) % mod);
    }
    void get_up_lt() {
    	rep(i, 1, n) rep(j, 1, m) up[i][j] = lt[i][j] = 0x3f3f3f3f;
    	rep(i, 1, q) {
    		rep(j, a[i].x + 1, a[i].xx)
    			lt[j][a[i].yy] = Min(a[i].y, lt[j][a[i].yy]);
    		rep(j, a[i].y + 1, a[i].yy)
    			up[a[i].xx][j] = Min(a[i].x, up[a[i].xx][j]);
    	}
    	per(i, n, 1) per(j, m, 1) {
    			if(j < m) lt[i][j] = Min(lt[i][j + 1], lt[i][j]);
    			if(i < n) up[i][j] = Min(up[i + 1][j], up[i][j]);
    			if(lt[i][j] >= j) lt[i][j] = 0x3f3f3f3f;
    			if(up[i][j] >= i) up[i][j] = 0x3f3f3f3f;
    		}
    }
    void solve() {
    	gi(n), gi(m), gi(q);
    	rep(i, 1, q) gi(a[i].x), gi(a[i].y), gi(a[i].xx), gi(a[i].yy);
    	get_up_lt();
    	rep(i, 1, n) Lt[i].init(m); rep(i, 1, m) Up[i].init(n);
    	rep(i, 1, n) rep(j, 1, m) f[i][j] = Node(1, 1);
    	rep(i, 1, n) rep(j, 1, m) {
    		Lt[i].push(j, f[i][j]), Up[j].push(i, f[i][j]);
    		if(lt[i + 1][j + 1] != 0x3f3f3f3f)
    			f[i + 1][j + 1] = f[i + 1][j + 1] + Lt[i].ask(lt[i + 1][j + 1]);
    		if(up[i + 1][j + 1] != 0x3f3f3f3f)
    			f[i + 1][j + 1] = f[i + 1][j + 1] + Up[j].ask(up[i + 1][j + 1]);
    		if(up[i + 1][j + 1] != 0x3f3f3f3f && lt[i + 1][j + 1] != 0x3f3f3f3f &&
    			f[i][j].len + 1 == f[i + 1][j + 1].len)
    			f[i + 1][j + 1].s = (f[i + 1][j + 1].s - f[i][j].s + mod) % mod;
    	}
    	ans = Node(0, 0);
    	rep(i, 1, n) rep(j, 1, m) ans = ans + f[i][j];
    	printf("%d %d
    ", ans.len, ans.s);
    }
    int main() {
    //	file();
    	for(scanf("%d", &T); T; --T) solve();
    	return 0;
    }
    
  • 相关阅读:
    Nacos(六):多环境下如何“管理”及“隔离”配置和服务
    nginx 反向代理配置(二)
    nginx 反向代理配置(一)
    nginx的access_log与error_log
    MySQL 慢查询日志
    php-fpm 慢日志查询
    理解 OAuth2.0
    如何在 Apache 里修改 PHP 配置
    Go-常见的面试题(一)
    Go 嵌入类型
  • 原文地址:https://www.cnblogs.com/daniel14311531/p/10507150.html
Copyright © 2011-2022 走看看