• 2019 ICPC Asia Yinchuan Regional


    Contest Info


    [Practice Link](https://www.jisuanke.com/contest/5527?view=challenges)
    Solved A B C D E F G H I J K L M N
    9/14 O O - O - O O O O - O - - O
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    A. Girls Band Party

    题意:

    给出一个(n),然后给出(n)个名字、颜色、分数,然后给出(5)个奖励名字和一个奖励颜色,从(n)个中选择(5)个,选出的(5)个名字不重复,如果出现一个奖励名字,则获得(10\%)的总评分数,出现一个奖励颜色,则获得(20\%)的总评分数,求最大的总评分数

    思路:

    先将每个名字分为奖励颜色和非奖励颜色两种,分别取(max),然后枚举每个奖励名字的不选、选择奖励颜色、选择非奖励颜色三种情况,然后对于剩下需要选择的名字,从非奖励颜色中取前(10)个二进制枚举进行选择,剩下的从奖励颜色中选择

    代码:

    view code
    #include <bits/stdc++.h>
    
    using namespace std;
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template <class T, class... Ts>
    void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
    
    const int N = 1e5 + 10;
    
    struct node {
    	string name;
    	string col;
    	int val;
    
    }a[N];
    
    struct qnode {
    	int id;
    	int val;
    
    	qnode() {}
    
    	qnode(int id, int val): id(id), val(val) {}
    
    	bool operator < (const qnode &other) const {
    		return val > other.val;
    	}
    };
    
    int res;
    int n, tot;
    string name[10], col;
    int bor[10][2];
    int b[N][2];
    map<string, int>mp;
    vector<qnode> vec[2];
    int vis[N];
    
    int getId(const string &t) {
    	if (mp.count(t)) return mp[t];
    	mp[t] = ++tot;
    	return mp[t];
    }
    
    void gao(int pos, int match_name, int match_col, int sum) {
    	if (pos > 5) {
    		int limit = min(10, (int)vec[0].size()), sub = 5 - match_name;
    		for (int S = 0; S < (1 << limit); ++S) {
    			int tmp = sum;
    			int match = match_col;
    			int need = sub;
    			for (int i = 0; i < limit; ++i) {
    				if (S & (1 << i)) {
    					vis[vec[0][i].id] = 1;
    					tmp += vec[0][i].val;
    					need--;
    				} 
    			}
    			if (need > 0) {
    				for (auto &it : vec[1]) {
    					if (!vis[it.id]) {
    						need--;
    						tmp += it.val;
    						match++;
    						if (need == 0) break;
    					}
    				}
    			}
    			if (need == 0) {
    				double other = 0.1 * match_name + 0.2 * match;
    				tmp = tmp * (1.0 + other);
    				res = max(res, tmp);
    			}
    			for (int i = 0; i < limit; ++i) {
    				vis[vec[0][i].id] = 0;
    			}
    		}
    		return ;
    	} else {
    		gao(pos + 1, match_name, match_col, sum);
    		if (bor[pos][0])
    			gao(pos + 1, match_name + 1, match_col, sum + bor[pos][0]);
    		if (bor[pos][1])
    			gao(pos + 1, match_name + 1, match_col + 1, sum + bor[pos][1]);
    	}
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	int T;
    	cin >> T;
    	while (T--) {
    		cin >> n;
    		
    		res = 0;
    		memset(bor, 0, sizeof bor);
    		tot = 0;
    		mp.clear();
    		vec[0].clear(), vec[1].clear();
    		memset(b, 0, sizeof b);
    
    		for (int i = 1; i <= n; ++i) {
    			cin >> a[i].name >> a[i].col >> a[i].val;
    		}
    		for (int i = 1; i <= 5; ++i) {
    			cin >> name[i];
    		}
    		cin >> col;
    		for (int i = 1; i <= 5; ++i) getId(name[i]);
    		for (int i = 1; i <= n; ++i) {
    			int id = getId(a[i].name);
    			if (id <= 5) {
    				if (a[i].col == col) {
    					bor[id][1] = max(bor[id][1], a[i].val);
    				} else {
    					bor[id][0] = max(bor[id][0], a[i].val);
    				}
    			} else {
    				if (a[i].col == col) {
    					b[id][1] = max(b[id][1], a[i].val);
    				} else {
    					b[id][0] = max(b[id][0], a[i].val);
    				}
    			}
    		}
    		for (int i = 6; i <= tot; ++i) {
    			for (int j = 0; j < 2; ++j) {
    				if (b[i][j])
    					vec[j].push_back(qnode(i, b[i][j]));
    			}	
    		}
    		sort(vec[0].begin(), vec[0].end());
    		sort(vec[1].begin(), vec[1].end());
    		gao(1, 0, 0, 0);
    		printf("%d
    ", res);
    	}
    	return 0;
    }
    

    B. So Easy

    题意:
    给出一个(n cdot n)的矩形,这个矩形(a_{i, j})的初始值为(0),它每次能够选择一行或者一列加上(1),现在遮住某个位置的数,让你还原这个数。

    思路:
    考虑倒退操作,不考虑遮住的那个数,然后枚举每行,每列,每次选择行最小,列最小将整行整列减去即可还原出那个数。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e3 + 10;
    int n, a[N][N];
    
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		int x = -1, y = -1;
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= n; ++j) {
    				scanf("%d", &a[i][j]);
    				if (a[i][j] == -1) {
    					x = i, y = j;
    					a[i][j] = 0;
    				}
    			}
    		}
    		for (int i = 1; i <= n; ++i) {
    			int Min = 1e9;
    			for (int j = 1; j <= n; ++j) {
    				if (x == i && y == j) continue;
    				Min = min(Min, a[i][j]);
    			}
    			for (int j = 1; j <= n; ++j) {
    				a[i][j] -= Min;
    			}
    		}
    		for (int j = 1; j <= n; ++j) {
    			int Min = 1e9;
    			for (int i = 1; i <= n; ++i) {
    				if (x == i && y == j) continue;
    				Min = min(Min, a[i][j]);
    			}
    			for (int i = 1; i <= n; ++i) {
    				a[i][j] -= Min;
    			}
    		}
    		printf("%d
    ", -a[x][y]);
    	}
    	return 0;
    }
    

    D. Easy Problem

    题意:
    定义一个序列((a_1, a_2, cdots, a_n))是一个((n, m, d)-good)当且仅当(1 leq a_i leq m(1 leq i leq n))并且(gcd(a_1, a_2, cdots, a_n) = d)
    (f(a, k) = (a_1a_2cdots a_n)^k),现在给出(n, m, d, k),让你求所有合法的((n, m, d)-good)的序列(a)(f(a, k))

    思路:
    题目要求的东西等价于:

    [egin{eqnarray*} f(d) = sumlimits_{a_1 = 1}^m sumlimits_{a_2 = 1}^m cdots sumlimits_{a_n = 1}^m [gcd(a_1, a_2, cdots, a_n) = d](a_1a_2cdots a_n)^k end{eqnarray*} ]

    那么我们令:

    [egin{eqnarray*} g(d) = sumlimits_{a_1 = 1}^m sumlimits_{a_2 = 1}^m cdots sumlimits_{a_n = 1}^m [d | gcd(a_1, a_2, cdots, a_n)](a_1a_2cdots a_n)^k end{eqnarray*} ]

    显然有:

    [egin{eqnarray*} g(d) = (sumlimits_{d;|;i} i^k)^n end{eqnarray*} ]

    莫比乌斯反演有:

    [egin{eqnarray*} f(d) &=& sumlimits_{d;|;i} mu(frac{i}{d})g(i) \ &=& sumlimits_{d;|;i} mu(frac{i}{d}) (sumlimits_{i;|;j} j^k)^n end{eqnarray*} ]

    所以:

    [f(d) = sumlimits_{i = 1}^{leftlfloor m/d ight floor} mu(i) (sumlimits_{id;|;j} j^k)^n ]

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    const int N = 1e5 + 10, mod = 59964251;
    int pri[N], check[N], mu[N], n, m, d, K, phi; 
    char s[N]; 
    void sieve() {
    	memset(check, 0, sizeof check);
    	*pri = 0;
    	mu[1] = 1;
    	for (int i = 2; i < N; ++i) {
    		if (check[i] == 0) {
    			pri[++*pri] = i;
    			mu[i] = -1;
    		}
    		for (int j = 1; j <= *pri; ++j) {
    			if (i * pri[j] >= N) break;
    			check[i * pri[j]] = 1;
    			if (i % pri[j] == 0) {
    				mu[i * pri[j]] = 0;
    				break;
    			} else {
    				mu[i * pri[j]] = -mu[i];
    			}
    		}
    	}
    }
    
    int eular(int n) {
    	int ans = n;
    	for (int i = 2; i * i <= n; ++i) {
    		if (n % i == 0) {
    			ans -= ans / i;
    			while (n % i == 0) 
    				n /= i;
    		}
    	}
    	if (n > 1) ans -= ans / n;
    	return ans;
    }
    
    ll gcd(ll a, ll b) {
    	return b ? gcd(b, a % b) : a;
    }
    
    ll qmod(ll base, ll n) {
    	ll res = 1;
    	while (n) {
    		if (n & 1) res = res * base % mod;
    		base = base * base % mod;
    		n >>= 1;
    	}
    	return res;
    }
    
    int getMod(int mod) {
    	int res = 0;
    	for (int i = 1; s[i]; ++i) {
    		res = (res * 10 + s[i] - '0') % mod;
    	}
    	return res;
    }
    
    int main() {
    	phi = eular(mod);
    	sieve(); 	
    //	cout << phi << endl;
    	int _T; scanf("%d", &_T);
    	while (_T--) {
    		scanf("%s%d%d%d", s + 1, &m, &d, &K);
    		int len = strlen(s + 1);
    		if (len <= 9) {
    			n = 0;
    			for (int i = 1; s[i]; ++i) {
    				n = n * 10 + s[i] - '0';
    			}
    		} else {
    			n = getMod(phi);
    			if (getMod(643) == 0 || getMod(93257) == 0) {
    				n += phi;
    			}
    		}
    		ll res = 0;
    		for (int i = 1; i <= m / d; ++i) {
    			int base = 0;
    			for (int j = i * d; j <= m; j += i * d) {
    				base += qmod(j, K);
    				base %= mod;
    			}
    			res += 1ll * mu[i] * qmod(base, n) % mod;
    			res = (res + mod) % mod;
    		}
    		printf("%lld
    ", res);
    	}
    	return 0;
    }
    

    E. XOR Tree

    题意:
    定义一个multiset的权值为里面任意两个数的异或和的平方的和。
    现在给出一棵有根树((1)为根),每个点有点权,定义(p(x, k))(x)子树中距离(x)不超过(k)的所有点的点权构成的multiset的权值,现在要对每个(i in [1, n])(p(i, k))

    F. Function!

    G. Pot!!

    裸的线段树。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    int n, q;
    struct SEG {
    	struct node {
    		int Max, lazy;
    		node() { Max = lazy = 0; }
    		void up(int x) {
    			Max += x;
    			lazy += x;
    		}
    		node operator + (const node &other) const {
    			node res = node();
    			res.Max = max(Max, other.Max);
    			return res;
    		}
    	}t[N << 2];
    	void build(int id, int l, int r) {
    		t[id] = node();
    		if (l == r) return;
    		int mid = (l + r) >> 1;
    		build(id << 1, l, mid);
    		build(id << 1 | 1, mid + 1, r);
    	}
    	void down(int id) {
    		int &lazy = t[id].lazy;
    		if (lazy) {
    			t[id << 1].up(lazy);
    			t[id << 1 | 1].up(lazy);
    			lazy = 0;
    		}
    	}
    	void update(int id, int l, int r, int ql, int qr, int v) {
    		if (l >= ql && r <= qr) {
    			t[id].up(v);
    			return;
    		}
    		int mid = (l + r) >> 1;
    		down(id);
    		if (ql <= mid) update(id << 1, l, mid, ql, qr, v);
    		if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v);
    		t[id] = t[id << 1] + t[id << 1 | 1];
    	}
    	int query(int id, int l, int r, int ql, int qr) {
    		if (l >= ql && r <= qr) return t[id].Max;
    		int mid = (l + r) >> 1;
    		down(id);
    		int res = 0;
    		if (ql <= mid) res = max(res, query(id << 1, l, mid, ql, qr));
    		if (qr > mid) res = max(res, query(id << 1 | 1, mid + 1, r, ql, qr));
    		return res;
    	}
    }seg[4];
    
    int main() {
    	int id[] = {0, 0, 0, 1, 0, 2, 0, 3, 0};
    	vector <vector<int>> vec;
    	vec.resize(15);
    	for (int i = 2; i <= 10; ++i) {
    		int x = i;
    		vec[i].clear();
    		for (int j = 2; j <= x; ++j) {
    			while (x % j == 0) {
    				vec[i].push_back(j);
    				x /= j;
    			}
    		}
    	//	cout << i << endl;
    	//	for (auto &it : vec[i])
    	//		cout << it << " ";
    	//	cout << endl;
    	}
    	while (scanf("%d%d", &n, &q) != EOF) {
    		for (int i = 0; i < 4; ++i) seg[i].build(1, 1, n);
    		char op[20]; int l, r, x;
    		while (q--) {
    			scanf("%s%d%d", op, &l, &r);
    			if (op[1] == 'U') {
    				scanf("%d", &x);
    				for (auto &it : vec[x]) {
    					seg[id[it]].update(1, 1, n, l, r, 1);
    				}
    			} else {
    				int res = 0;
    				for (int i = 0; i < 4; ++i) {
    					res = max(res, seg[i].query(1, 1, n, l, r));
    				}
    				printf("ANSWER %d
    ", res);
    			}
    		}	
    	}
    	return 0;
    }
    

    H. Delivery Route

    题意:
    给出一张图,有(x)条无向边,有(y)条有向边,保证无向边都是正权值,有向边可能有负权值,并且保证如果一条有向边(a_i ightarrow b_i),那么在该图中,(b_i)不可能到达(a_i)
    现在询问从(s)出发到任意一点的最短路。

    思路:
    我们考虑如果只考虑有向边,那么是一个(DAG),那么把无向边连成的每个联通块看成一个新点,并且有有向边将他们连接起来,他们也是一个(DAG)
    并且无向图的连通块里面没有负权边,可以跑dijkstra,然后根据拓扑序dp一下即可。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    using pII = pair<int, int>;
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template <class T, class... Ts>
    void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
    #define fi first
    #define se second
    const int N = 5e4 + 10, INF = 0x3f3f3f3f;
    int n, mx, my, s, id[N], d[N];
    //0 two-way 1 one-way
    vector <vector<pII>> G[3];
    vector <vector<int>> po;
    struct DSU {
    	int fa[N];
    	void init() { memset(fa, 0, sizeof fa); }
    	int find(int x) {
    		return fa[x] == 0 ? x : fa[x] = find(fa[x]);
    	}
    	void merge(int u, int v) {
    		int fu = find(u), fv = find(v);
    		if (fu != fv) {
    			fa[fu] = fv;
    		}
    	}
    }dsu;
    
    struct node {
    	int u, w;
    	node() {}
    	node(int u, int w) : u(u), w(w) {}
    	bool operator < (const node &other) const {
    		return w > other.w;
    	}
    };
    int dis[N], used[N];
    void Dijkstra(int S) {
    	priority_queue <node> pq;
    	pq.push(node(S, dis[S]));
    	while (!pq.empty()) {
    		int u = pq.top().u; pq.pop();
    		for (auto &it : G[0][u]) { 
    			int v = it.fi, w = it.se;
    			if (dis[v] > dis[u] + w) {
    				dis[v] = dis[u] + w;
    				pq.push(node(v, dis[v]));
    			}	
    		}
    	}
    }
    
    void Topo() {
    	queue <int> que;
    	for (int i = 1; i <= *id; ++i) {
    		if (d[i] == 0) {
    			que.push(i);
    		}
    	}	
    	while (!que.empty()) {
    		int u = que.front(); que.pop();
    		sort(po[u].begin(), po[u].end(), [&](int a, int b) { return dis[a] < dis[b]; });
    		for (auto &it : po[u]) {
    			Dijkstra(it);
    			for (auto &it2 : G[1][it]) {
    				int v = it2.fi, w = it2.se;
    				if (dis[it] < INF) {
    					dis[v] = min(dis[v], dis[it] + w);
    				}
    			}
    		}	
    		for (auto &it : G[2][u]) {
    			int v = it.fi;
    			if (--d[v] == 0) {
    				que.push(v);
    			}
    		}
    	}
    }
    
    int main() {
    	while (scanf("%d%d%d%d", &n, &mx, &my, &s) != EOF) {
    		for (int i = 1; i <= n; ++i) {
    			dis[i] = INF;
    		}
    		dis[s] = 0;
    		*id = 0;
    		G[0].clear(); G[1].clear();
    		G[0].resize(n + 1); G[1].resize(n + 1);
    		for (int i = 1, u, v, w; i <= mx; ++i) {
    			scanf("%d%d%d", &u, &v, &w);
    			G[0][u].push_back(pII(v, w));
    			G[0][v].push_back(pII(u, w));
    		}
    		for (int i = 1, u, v, w; i <= my; ++i) {
    			scanf("%d%d%d", &u, &v, &w);
    			G[1][u].push_back(pII(v, w));
    		}
    		dsu.init();
    		for (int u = 1; u <= n; ++u) {
    			for (auto &it : G[0][u]) {
    				int v = it.fi;
    				dsu.merge(u, v);
    			}
    		}
    		for (int u = 1; u <= n; ++u) {
    			if (dsu.fa[u] == 0)
    				id[u] = ++*id;
    		}
    		for (int u = 1; u <= n; ++u) {
    			if (dsu.fa[u]) {
    				id[u] = id[dsu.find(u)];
    			}
    		}
    	//	for (int i = 1; i <= n; ++i)
    	//		dbg(i, id[i]); 
    		po.clear(); po.resize(*id + 10);
    		G[2].clear(); G[2].resize(*id + 10);
    		memset(d, 0, sizeof d);
    		for (int u = 1; u <= n; ++u) {
    		    po[id[u]].push_back(u);	
    			for (auto &it : G[1][u]) { 
    				int v = it.fi;
    				if (id[u] != id[v]) {
    					G[2][id[u]].push_back(pII(id[v], v));
    					++d[id[v]];
    				}
    			}
    		}
    		Topo();
    		for (int i = 1; i <= n; ++i) {
    			if (dis[i] >= INF) puts("NO PATH");
    			else printf("%d
    ", dis[i]);
    		}
    		
    	}
    	return 0;
    }
    

    I. Base62

    题意:
    进制转换

    代码:

    view code
    
    def main():
        l = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
             'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
             'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
        x, y, z = input().split()
        x = int(x)
        y = int(y)
        num = 0
        for c in z:
            if ord('0') <= ord(c) <= ord('9'):
                num = num * x + ord(c) - ord('0')
            elif ord('A') <= ord(c) <= ord('Z'):
                num = num * x + ord(c) - ord('A') + 10
            else:
                num = num * x + ord(c) - ord('a') + 36
        if num == 0:
            print("0")
            return 
        res = ""
        while num > 0:
            tmp = num % y
            res = res + l[tmp]
            num = num // y
        # print(res)
        res = res[::-1]
        print(res)
    
    main()
    

    K. Largest Common Submatrix

    题意:
    给出两个(n cdot m)的矩形,并且里面的数是([1, nm])的排列。
    求两个矩形的最大公共子矩形,这里的大定义为面积。

    思路:
    考虑里面的数是一个排列,可以(O(n^2))处理出每个数向上拓展多少,向左右拓展多少,然后考虑每一行,肯定是某段连续的长度然后乘上这段最小的向上拓展的数量。
    向上拓展的这部分当成一个维,位置当成一维,丢进笛卡尔树里面跑一跑能跑出每个最小值管辖的范围,然后和左右扩展的范围求交,就是每个向上拓展数量在横向最远能扩展的范围。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    using pII = pair<int, int>; 
    #define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template <class T, class... Ts>
    void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
    #define fi first
    #define se second
    const int N = 1e3 + 10, INF = 0x3f3f3f3f;
    int n, m, a[N][N], b[N][N], l[N][N], r[N][N], num[N][N];
    pII c[N], id[N * N];
    
    struct CT {
    	struct node {
    		int id, val, fa;
    		int son[2];
    		node() {}
    		node (int id, int val, int fa) : id(id), val(val), fa(fa) {
    			son[0] = son[1] = 0;
    		}
    		bool operator < (const node &other) const {
    			return val < other.val;
    		}
    	}t[N];
    	int root;
    	void init() {
    		t[0] = node(0, -INF, 0);
    	}
    	void build(int n, int *a) {
    		for (int i = 1; i <= n; ++i) {
    			t[i] = node(i, a[i], 0);
    		}
    		for (int i = 1; i <= n; ++i) {
    			int k = i - 1;
    			while (t[i] < t[k]) {
    				k = t[k].fa;
    			}
    			t[i].son[0] = t[k].son[1];
    			t[k].son[1] = i;
    			t[i].fa = k;
    			t[t[i].son[0]].fa = i;
    		}
    		root = t[0].son[1];
    	}
    	int dfs(int u) {
    		if (!u) return 0;
    		c[u].fi = dfs(t[u].son[0]);
    		c[u].se = dfs(t[u].son[1]);
    		return c[u].fi + c[u].se + 1;
    	}
    }ct;
    
    int main() {
    	while (scanf("%d%d", &n, &m) != EOF) {
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= m; ++j) {
    				scanf("%d", &a[i][j]);
    			}
    		}
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= m; ++j) {
    				scanf("%d", &b[i][j]);
    				id[b[i][j]] = pII(i, j); 
    			}
    		}
    
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= m; ++j) {
    				if (j == 1) {
    					l[i][j] = j;
    				} else {
    					int pre = a[i][j - 1], now = a[i][j];
    					if (id[pre].fi == id[now].fi && id[pre].se == id[now].se - 1) {
    						l[i][j] = l[i][j - 1];
    					} else {
    						l[i][j] = j;
    					}
    				}
    			}
    			for (int j = m; j >= 1; --j) {
    				if (j == m) {
    					r[i][j] = j;
    				} else {
    					int nx = a[i][j + 1], now = a[i][j];
    					if (id[nx].fi == id[now].fi && id[nx].se == id[now].se + 1) {
    						r[i][j] = r[i][j + 1];
    					} else {
    						r[i][j] = j;
    					}
    				}
    			}
    		}
    		for (int j = 1; j <= m; ++j) {
    			for (int i = 1; i <= n; ++i) {
    				if (i == 1) {
    					num[i][j] = 1;
    				} else {
    					int pre = a[i - 1][j], now = a[i][j];
    					if (id[pre].fi == id[now].fi - 1 && id[pre].se == id[now].se) {
    						num[i][j] = num[i - 1][j] + 1;
    					} else {
    						num[i][j] = 1;
    					}
    				}
    			}
    		}
    		int res = 0;
    		for (int i = 1; i <= n; ++i) {
    		//	for (int j = 1; j <= m; ++j) {
    		//		dbg(i, j, l[i][j], r[i][j], num[i][j]);
    		//	}
    			ct.init();
    			ct.build(n, num[i]);
    			ct.dfs(ct.root);
    			for (int j = 1; j <= m; ++j) {
    				int tl = max(l[i][j], j - c[j].fi);
    				int tr = min(r[i][j], j + c[j].se);
    				res = max(res, (tr - tl + 1) * num[i][j]);
    			}
    		}
    		printf("%d
    ", res);
    	}
    	return 0;
    }
    

    N. Fibonacci Sequence

    纯输出题

  • 相关阅读:
    Uploader 文件上传
    filters过滤器的使用
    Calendar中遇到的问题
    中科院之旅
    Python基础教程:列表推导式详解
    不会也要知道的,Python四种实现排序的方法
    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案
    2021字节跳动校招秋招算法面试真题解题报告--leetcode206 反转链表,内含7种语言答案
    求协方差
    国外卡组织的 交换费-interchangefee(发卡行服务费) 和 银联对比
  • 原文地址:https://www.cnblogs.com/Dup4/p/11963769.html
Copyright © 2020-2023  润新知