Idea大全:捕捉忽视的灵感瞬间

Excellent Ideas

通过交换两个数的操作,使得一个排列\(a\)转变成另外一个排列\(b\),求最少的交换次数。

对于每一个\(i\)连一条\(a_i\)\(b_i\)的双向边,在图中求联通块数量\(c\),最少交换次数为\(n-c\)

\(x \ mod \ y\)要转化为\(x-y\times \lfloor \frac{x}{y}\rfloor\)然后分离开来处理。

出现值域很大但是具体值对问题没有实质性影响时,考虑离散化将问题简化.
本题中,\(1 \leq l<r\leq 10^9\),转移是 \(f[i] = max(f[i] , f[j] + 1)\) (条件: \(j\)行和\(i\)行至少有一个位置同为\(1\)

考虑到区间\([l,r]\)具体大小对问题没有影响,所以可以对区间进行离散化,就不用动态开点了。

删除边没有添加边方便,通常两者可以相互转化。(删除边和倒序添加边是等价的)

  1. 在一个字符串中删去一些元素和提取一些元素之间不等价。
  2. 求字符串删除元素后形成的串的种类/个数,可以用Substring DP来做:
    \(f_i\)表示第\(i\)个字符选择的方案数,\(f_i = \sum_{j=k}^{i-1} f_j \ (k = \max w [\ s_i = s_w])\)

这是由于\(1,...,k-1\)的信息都保存在\(f_k\)中了。

01-bfs搜索的本质是当前第一次搜索到的值一定是最优值,而动态插入的值可以让bfs搜索依然满足这个性质。
本题中当前能走的通,直接将其放在队列的首部,否则放在队尾,人为规定了bfs的优先级,可以简化复杂度。

dfs序和欧拉序将树上的问题转化为区级问题,本问题是二分求最大边的问题。
(欧拉序的构造)
第一种方法:

void dfs(int u) {
	sa[++tim] = u;
	dfn[u] = tim;
	for (son...) dfs(son);	
	sa[++tim] = u;
}
  • 性质1 :\(x\)节点的子树中的所有节点,都在第一次出现的\(x\)时刻后,第二次出现\(x\)时刻前,且不重不漏不多不少刚好出现\(2\)
  • 性质2 : \(x\)节点和\(y\)节点树上路径经过节点为,最后出现的\(x\)后,第一次出现的\(y\)之前,出现次数奇数次的节点+\(lca(x,y)\)
  • 应用 : 树上的问题,转化为区间问题求解。
    第二种方法:
void dfs(int u) {
	sa[++tim] = u;
	dfn[u] = tim;
	for (son...) {
		dfs(son);
		sa[++tim] = u;
	}
}
  • 性质1 :\(x\)节点中的子树中的所有节点,都在第一次出现\(x\)位置之后,最后一次出现\(x\)位置之后。
  • 性质2 :树上两点\(x,y\)\(lca\),在第一次出现\(x\)和第一次出现\(y\)位置之间,时间戳dfn,最小的位置。
  • 应用:预处理,并用ST表实现O(1)的lca查询。

(dfs序dfn的性质)
重要性质:节点\(x\)的子树在\(x\)出现位置\(pos\)的后面\(size[x]-1\)个,子树根后一定是连续排列的子树节点。
重要应用:述链剖分,将树上问题转化为区间问题。

\(n\)个变量\(x_i \in [l_i,r_i]\),询问是否存在一种解,让\(x_1+x_2+...+x_n = m\)

显然若\(m\in[\sum\limits_{i=1}^{n} l_i,\sum\limits_{i=1}^{n} r_i]\)都是合法情况。

构造的话,可以先将所有\(x_i = l_i\),然后对于每一个变量,尽可能将其增大,但让当前的\(\sum\limits_{i=1}^{n} x_i \leq m\)

\(n\)条线段\([l_i,r_i]\),要求选取尽可能少的点,让这些点能覆盖全部的线段。

考虑贪心,将这些线段按照右端点\(r_i\)升序排序,然后从\(1\)开始访问每一条线段,每次选取当前线段的右端点,因为之后遍历到的线段右端点一定比当前线段的右端点更靠右,为了让更多的线段被覆盖,就要让尽可能多的线段左端点在选取点的左侧,要求选取点要更靠右,因此,选取当前线段右端点是最佳的选择,选择更加左边的点不能获得更优的答案。

posted @ 2021-08-02 13:32  Maystern  阅读(45)  评论(0编辑  收藏  举报