首页 > 其他分享 >ABC372

ABC372

时间:2024-10-26 21:58:04浏览次数:1  
标签:200005 leq int pos 55 条边 ABC372

D

题目大意:

\(n\)座建筑排成一排,每座建筑的高度为\(h_i\)。\(\forall i \in [1,n]\),找出满足下面条件的\(j\)的数量:

  • 在建筑\(i\)到\(j\)中,没有建筑比\(j\)高的
  • \(j \in [i+1,n]\)

\(n\leq 2 \times 10^5\),\({h}\)是\(1\)到\(n\)的排列。

分析:

考虑\(i\)不好处理,我们改为考虑每个\(j\)可以贡献到哪些\(i\):即若\(h_j<h_i\),\(k\)从\(j-1\)开始,一直向左,直到\(h_k>h_j\)时,\(i\in [k+1,j-1]\)都会被贡献到(答案\(+1\))。所以,我们只需要快速找到在每个\(j\)往左第一个大于\(h_j\)的位置。这只需要我们把所有的\(i\)按照\(h_i\)从大到小排序,然后用一个\(set\)维护即可。至于区间修改单点查询,差分数组即可处理。

代码:

#include <bits/stdc++.h>

using namespace std;

int n, t, pos[200005], d[200005], h[200005], c[200005];

set < int > a;

int ask(int x)
{
	auto p = a.lower_bound(x);
	if (p == a.end()) return max(1, *(prev(p)));
	return *(prev(p));
}

int main()
{
	scanf("%d", &n); a.insert(0);
	for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]), pos[h[i]] = i;
	for (int i = n; i >= 1; i -- )
	{
		int l = ask(pos[i]), r = pos[i] - 1;
		if (l == 0) l = 1;
		a.insert(pos[i]);
		if (l > r || r == 0) continue;
		d[l] ++ , d[r + 1] -- ;
	}
	for (int i = 1; i <= n; i ++ ) d[i] += d[i - 1], printf("%d ", d[i]);
	puts("");
	return 0;
}

F

题目大意:

\(n\)个点的有向图共有\(n+m\)条边。\(\forall i \in [1,n]\),\(i\)至\(i+1\)存在一条边(\(n+1\)对应\(1\))。\(\forall i \in [1,m]\),\(x_i\)至\(y_i\)存在一条边。求下列方案数:从点\(1\)开始,恰好走\(k\)步。答案对\(998244353\)取模。\(n,k\leq 2 \times 10^5,m\leq 50\)。无重边自环。

分析:

\(O((n+m)k)\)的dp是显然的,但是无法通过。注意到虽然有\(n+m\)条边,但是其中的\(n\)条边形式都是一致的,而\(m\)又很小,复杂度瓶颈在\(n\)。于是我们考虑固定这\(n\)条边不动,让\(n\)个点去动(即:某条边\((i,i+1)\),把\(i+1\)当成\(i\),这样就相当于自己转移到自己,即保留原来的值,就不用考虑这条边了)。设 \(d_i\) 为走到节点 \(i\) 的方案数。首先,为了处理方便,不妨将所有节点的标号减 \(1\),这样旋转操作可以转化为标号取模操作(常用)。在将点整体移动的情况下,我们可以忽略对原环上边的转移。边 \((x,y)\) 在第 \(t\) 次转移时的实际效果是

\[d_{(y-t)\bmod n}\to d_{(y-t)\bmod n}+d_{(x-t+1)\bmod n} \]

模拟一下即可得到上述转移。例如,\(n=8,(x,y)=(2,4),t=1\)时,实际转移效果为\((2,3)\)。这是因为我们把\(i+1\)当成了\(i\)。另外,由于所有操作需要同时进行,所以需要缓存值后再操作。

代码:

#include <bits/stdc++.h>

using namespace std;

const int mod = 998244353;

int n, m, k, add[55][2], x[55], y[55], dp[200005];

int main()
{
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 1; i <= m; i ++ ) scanf("%d%d", &x[i], &y[i]), x[i] -- , y[i] -- ;
	dp[0] = 1;
	for (int i = 1; i <= k; i ++ )
	{
		for (int j = 1; j <= m; j ++ ) add[j][0] = (y[j] - i % n + n) % n, add[j][1] = dp[(x[j] - i % n + 1 + n) % n];
		for (int j = 1; j <= m; j ++ ) dp[add[j][0]] = (dp[add[j][0]] + add[j][1]) % mod;
	}
	int res = 0;
	for (int i = 0; i < n; i ++ ) res = (res + dp[i]) % mod;
	printf("%d\n", res);
	return 0;
}

标签:200005,leq,int,pos,55,条边,ABC372
From: https://www.cnblogs.com/andysj/p/18473056

相关文章

  • abc372E K-th Largest Connected Components
    有N个顶点的无向图,最初没有边,接下来有Q组询问,格式如下:1uv:在顶点u和v之间加一条边;2xk:问与顶点v连通的分量中,顶点编号第k大的是谁?如果不存在,输出-1.1<=N,Q<=2E5,1<=u<v<=N,1<=x<=N,1<=k<=10分析:由于k比较小,直接用vector维护连通分量的顶点集合,在合并时,如果顶点数超过k,......
  • abc372D Buildings
    N幢楼排成一行,第i号楼的高度为H[i]。对于每幢楼,右边有多少幢楼满足两楼之间的楼高都不超过右侧楼高?1<=N<=2E5,1<=H[i]<=N,H[i]!=Hj分析:单调栈求出各幢楼左边最近的比它高的楼,对于j号楼,假设它左边最近的比它高的楼号为i,那么j对区间[i,j-1]中每个下标都有1的贡献,可以用差分来维......
  • 题解:AT_abc372_e [ABC372E] K-th Largest Connected Components
    题意给出\(q\)个操作。将\(u\)和\(v\)连边。问\(u\)所在的连通块中编号第\(k\)大的点。思路连通块很容易想到并查集,求第\(k\)大可以用平衡树(虽然赛时没看到\(k\le10\)),合并时将信息从将小的连通块合并到大的连通块,这样可以减少时间复杂度。什么?你不会写平衡......
  • ABC372 F 题解
    F-TeleportingTakahashi2先把问题转化一下:把环断开成链,复制\((K+1)\)层,每走一步就相当于前进一层:可以想到一个简单的dp:设\(f(i,j)\)表示走到第\(i\)层第\(j\)个位置的方案数。初始化:\(f(0,1)=1\),其它均为\(0\),表示Takahashi从第\(0\)层的\(1\)位置......
  • ABC372 Review
    ABC372ReviewA语言基础题B类似于二进制拆分,就像跳LCA的时候一样,尽可能多地选大的即可。C一个位置的字母被改变仅仅会对相邻两个位置之类的答案产生影响,暴力统计即可。D对于每一个\(i\)去暴力地统计\(j\)显然是不可行的,所以可以转而想一想每个\(j\)会对答案产生多......
  • 题解:AT_abc372_f [ABC372F] Teleporting Takahashi 2
    题意给出一个\(n\)个点的有向图,点\(i\)连向点\((i+1)\),点\(n\)连向点\(1\)。再给你\(m\)条额外边。你的初始位置为\(1\),问你移动\(k\)步的不同方案数(仅当路径不同时两个方案不同)。思路先想怎样暴力转移,显然移动\(k\)步到达一个点的方案数为所有跟这个点连边的移......
  • 题解:AT_abc372_e [ABC372E] K-th Largest Connected Components
    博客内食用更佳这道题的\(k\le10\)其实没什么用,代码区别仅在于手写平衡树和使用内置容器。这道题让查询与一个节点相连的所有点的信息,所以不难想到并查集。又因为让查询第\(k\)大,所以不难想到平衡树和线段树启发式合并。至此思路明显。我们对并查集中的每个节点开一个平......
  • 题解:AT_abc372_c [ABC372C] Count ABC Again
    博客内食用更佳乍一看好像是数据结构。我们结合题目所求内容考虑。对于每次修改,能对答案产生影响的最多只能是当前字符向前和向后延伸\(2\)个元素所构成的长为\(5\)的子串。那么我们先\(\mathcal{O}(n)\)计算出来初始答案。每次修改的时候,不妨先把\(i-2\simi\)和\(i-......
  • abc372_E
    E-K-thLargestConnectedComponents思路由于要求求所求点第\(k\)大点,所以在每个点上开一个\(set\)就可以了,因为\(k\)小于\(10\)所以直接遍历取第\(k\)大就行了,当连接两点的时候,使用并查集维护,因为要合并,但直接合并会超时,所以使用启发式合并其中有一个重要的点就是启发式合......
  • ABC372 (D,E)
    ABC372(D,E)D一道比较简单的二分查找题目。观察到每个数能成为\(j\)的条件是独立的,因此想到统计每个数能成为它前面哪些数的\(j\)。对于每个\(ed​\),二分\(1\simed-1​\)中最后一个大于\(h[ed]​\)的数的位置\(st​\),那么\(h[ed]​\)可作为\(st\simed-1......