首页 > 其他分享 >AtCoder Grand Contest 041 F Histogram Rooks

AtCoder Grand Contest 041 F Histogram Rooks

时间:2023-09-07 21:55:41浏览次数:34  
标签:AtCoder Rooks 格子 Contest int 钦定 贡献 maxn ll

洛谷传送门

AtCoder 传送门

神题!!!!!!!!!/bx

全部格子都被覆盖不好处理,考虑钦定 \(k\) 个格子不被覆盖,容斥系数就是 \((-1)^k\)。

发现网格的行不一定连续,但是列是连续的。如果一列有格子被钦定,那么这一列就不能放棋子。

由此想到枚举不能放棋子的列(至少有一个棋子被钦定的列)集合 \(S\),把每个行连续段的贡献相乘。

设行连续段有 \(len\) 个格子,其中 \(p\) 个格子所在列属于 \(S\),那么如果这个行连续段没有格子被钦定,每个所在列不属于 \(S\) 的格子都能放棋子,贡献是 \(2^{len - p}\);如果至少一个格子被钦定,枚举钦定了几个格子,得贡献为 \(\sum\limits_{i = 1}^p \binom{p}{i} (-1)^i = -[p > 0]\)。

但是很容易看出来一个问题,就是 \(S\) 中的列不一定至少有一个棋子被钦定。

仍然考虑容斥,钦定 \(T \subseteq S\) 为没有格子被钦定的列集合,容斥系数为 \((-1)^{|T|}\);设行连续段中有 \(q\) 个格子所在列属于 \(T\),那么如果这个行连续段没有格子被钦定,贡献仍然是 \(2^{len - p}\);如果至少一个格子被钦定,贡献为 \(\sum\limits_{i = 1}^{p - q} \binom{p - q}{i} (-1)^i = -[p - q > 0] = -[p > q]\)。计算答案就把每个行连续段这样的贡献相乘即可。

枚举 \(S, T\) 复杂度显然过高,考虑简化。

首先我们发现只有连续段中 \(|S| = p, [|S| > |T|] = [p > q]\) 在计算贡献时有用。

然后考虑把网格按 \(h_i\) 的笛卡尔树剖分成若干个行连续段的贡献相同的形式,像这样(图来自 Verdandi):

建出笛卡尔树,发现相邻的色块(父亲与儿子)相互依赖。比如上图,绿色块的 \(p\) 等于第 \(1, 3, 5\) 列是否被 \(S\) 包含加上橙色块的 \(p\) 加上黄色块的 \(p\) 加上粉色块的 \(p\),同理,\([p > q]\) 是所有子结点的 \([p > q]\) 的或(或者可以维护 \([p = q]\),就是所有子结点的 \([p = q]\) 的与)。

考虑一个树形 dp,\(f_{u, i, 0/1}\) 表示 \(u\) 结点目前 \(p = i\),\([p = q] = 0/1\) 的容斥系数 \((-1)^{|T|}\) 乘贡献之和。我们首先考虑空行,也就是 \(f_{u, 0, 0} = f_{u, 1, 0} = 1, f_{u, 1, 1} = -1\)(对于 \(h_i\) 相同的子结点强制钦定一个父子顺序)。然后树形背包合并上来子结点。最后乘上若干行(设为 \(b_u\))连续段的贡献,也就是 \((2^{sz_u - p} - [p > q])^{b_u}\)。

快速幂计算贡献是 \(O(n^2 \log n)\),容易通过预处理这个贡献做到 \(O(n^2)\)。

code
// Problem: F - Histogram Rooks
// Contest: AtCoder - AtCoder Grand Contest 041
// URL: https://atcoder.jp/contests/agc041/tasks/agc041_f
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 410;
const int logn = 10;
const ll mod = 998244353;

ll n, a[maxn], stk[maxn], top, L[maxn], R[maxn], pw[maxn][maxn][2];
pii h[maxn][logn];
bool vis[maxn];
vector<int> G[maxn];

inline pii qmin(int l, int r) {
	int k = __lg(r - l + 1);
	return min(h[l][k], h[r - (1 << k) + 1][k]);
}

int build(int l, int r) {
	if (l > r) {
		return 0;
	}
	int mid = qmin(l, r).scd;
	int p = build(l, mid - 1), q = build(mid + 1, r);
	if (p) {
		G[mid].pb(p);
	}
	if (q) {
		G[mid].pb(q);
	}
	return mid;
}

ll f[maxn][maxn][2], sz[maxn], g[maxn][2], b[maxn];

inline void upd(ll &x, ll y) {
	((x += y) >= mod) && (x -= mod);
}

void dfs(int u) {
	sz[u] = 1;
	f[u][0][1] = f[u][1][0] = 1;
	f[u][1][1] = mod - 1;
	for (int v : G[u]) {
		b[v] = a[v] - a[u];
		dfs(v);
		for (int i = 0; i <= sz[u]; ++i) {
			g[i][0] = f[u][i][0];
			g[i][1] = f[u][i][1];
			f[u][i][0] = f[u][i][1] = 0;
		}
		for (int i = 0; i <= sz[u]; ++i) {
			for (int j = 0; j <= sz[v]; ++j) {
				upd(f[u][i + j][1], g[i][1] * f[v][j][1] % mod);
				upd(f[u][i + j][0], (g[i][1] * f[v][j][0] % mod + g[i][0] * (f[v][j][0] + f[v][j][1]) % mod) % mod);
			}
		}
		sz[u] += sz[v];
	}
	for (int i = 0; i <= sz[u]; ++i) {
		f[u][i][0] = f[u][i][0] * pw[sz[u] - i][b[u]][0] % mod;
		f[u][i][1] = f[u][i][1] * pw[sz[u] - i][b[u]][1] % mod;
	}
}

void solve() {
	scanf("%lld", &n);
	ll k = 1;
	for (int i = 0; i <= n; ++i) {
		pw[i][0][0] = pw[i][0][1] = 1;
		for (int j = 1; j <= n; ++j) {
			pw[i][j][0] = pw[i][j - 1][0] * (k + mod - 1) % mod;
			pw[i][j][1] = pw[i][j - 1][1] * k % mod;
		}
		k = k * 2 % mod;
	}
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		h[i][0] = mkp(a[i], i);
	}
	for (int j = 1; (1 << j) <= n; ++j) {
		for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
			h[i][j] = min(h[i][j - 1], h[i + (1 << (j - 1))][j - 1]);
		}
	}
	int rt = build(1, n);
	b[rt] = a[rt];
	dfs(rt);
	ll ans = 0;
	for (int i = 0; i <= n; ++i) {
		upd(ans, f[rt][i][0]);
		upd(ans, f[rt][i][1]);
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,Rooks,格子,Contest,int,钦定,贡献,maxn,ll
From: https://www.cnblogs.com/zltzlt-blog/p/17686173.html

相关文章

  • AtCoder Beginner Contest 318 - D(状压 dp)
    目录D-GeneralWeightedMaxMatchingD-GeneralWeightedMaxMatching题意给定无向图,边有边权。让你选择一组边,满足任意两边不相交且总边权和最大。顶点数$\le16$思路状压DP求解该问题状态:利用n位二进制表示每个顶点是否已经被选择,0表示该顶点未选,1表示当前......
  • 2022 International Collegiate Programming Contest, Jinan Site AEKM
    2022InternationalCollegiateProgrammingContest,JinanSite-CodeforcesAEKMA.Tower思路:思维+贪心由于我们只能进行\(+1,-1\)和\\(2\)的操作。显然的,我们能大幅度改变一个数是除\(2\)的操作,并且最后化成的一样的那个数一定不会大于当且的任何一个数,因为这样肯定......
  • The 16-th BIT Campus Programming Contest - Onsite Round
    链接:https://codeforces.com/gym/104025A.Giftsinbox#include"bits/stdc++.h"usingnamespacestd;usingi64=longlong;intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intn,m,h;cin>>n>>m>&......
  • [题解] AtCoder Beginner Contest 308 A~G
    AtCoderBeginnerContest308A~GA.NewSchemevoidMain(){vector<i64>a(8);for(auto&x:a)cin>>x;if(!is_sorted(a.begin(),a.end())&&!all_of(a.begin(),a.end(),[](auto&x){returnx%25!=0||!(100......
  • The 2022 ICPC Asia Nanjing Regional Contest
    链接:https://codeforces.com/gym/104128A.Stop,YesterdayPleaseNoMore#include"bits/stdc++.h"usingnamespacestd;usingi64=longlong;voidsolve(){intn,m,k;cin>>n>>m>>k;strings;cin>>......
  • The 2022 ICPC Asia Hangzhou Regional Programming Contest
    The2022ICPCAsiaHangzhouRegionalProgrammingContestNoBugNoGame  #include<bits/stdc++.h>usingnamespacestd;#defineendl"\n"#defineintlonglongtypedeflonglongll;constintN=3e3+10;intf[N][N][2];signedm......
  • The 18th Heilongjiang Provincial Collegiate Programming Contest
    链接:https://codeforces.com/gym/104363A.MagicComputer#include"bits/stdc++.h"usingnamespacestd;usingi64=longlong;constexprintP=998244353;i64power(i64a,i64b){i64res=1;for(;b;b>>=1,a=a*a%P){......
  • The 10th Shandong Provincial Collegiate Programming Contest
    链接:https://codeforces.com/gym/104459A#include"bits/stdc++.h"usingnamespacestd;usingi64=longlong;stringS[]={"Monday","Tuesday","Wednesday","Thursday","Friday&q......
  • 【题解】AtCoder Beginner Contest 318(D - Ex)
    赛时过了A-G,Ex仿佛猜到了结论但是完全不懂多项式科技,就炸了。大家好像都秒了A,B,C就不写了。D.GeneralWeightedMaxMatching题目描述:给你一个加权无向完全图,图中有\(N\)个顶点,编号从\(1\)到\(N\)。连接顶点\(i\)和\(j\)的\((i<j)\)的权重为\(D_{i,j}\)。在......
  • AtCoder Beginner Contest 318
    A-FullMoonProblemStatementTakahashilikesfullmoons.Lettodaybeday\(1\).Thefirstdayonoraftertodayonwhichhecanseeafullmoonisday\(M\).Afterthat,hecanseeafullmoonevery\(P\)days,thatis,onday\(M+P\),day\(......