热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Codeforces1109F】SashaandAlgorithmofSilence'sSounds题解

题目链接【Codeforces1109F】SashaandAlgorithmofSilence'sSounds做法当区间$[l,r]$中不存在环且点数与边数之差为$1$时

题目链接

【Codeforces 1109F】 Sasha and Algorithm of Silence's Sounds


做法

当区间 $ [l, r] $ 中不存在环且点数与边数之差为 $ 1 $ 时是一棵树。当 $ r $ 增加时, $ l $ 也会增加,所以只要维护两个端点。

对于环的部分,可以用 $ LCT $ 快速维护( $ findroot $ 后要 $ splay $ 一下,否则会 $ T $)。

对于维护点数与边数之差,可以用线段树维护针对当前询问左端点为某个位置时点数与边数之差, $ r $ 增加时直接继承上一个 $ r $ 。若新加的点 $ r $ ,则线段树区间 $ [l, r] $ 的权值加一;若新加的点 $ r $ 对 $ k \in [l, r] $ 有边,则线段树区间 $ [l, k] $ 的权值减一。然后数线段树中权值为 $ 1 $ 的位置的个数即可。

复杂度 $ O(n \log n) $ 。

#include
#define lc ch[0][u]
#define rc ch[1][u]
using namespace std;
typedef long long ll;
const int N= 1010, M = 200010;
const int dir[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
int n, m, lb = 1, rb = 1;
int a[N][N], idx[M], idy[M];
int fa[M], ch[2][M], sta[M], top; bool rv[M];
int tr[M * 4], sum[M * 4], lz[M * 4], fst, snd;
ll ans = 1;
inline int Min(const int &x, const int &y) { return x inline bool nroot(int u) { return ch[0][fa[u]] == u || ch[1][fa[u]] == u; }
inline void Rev(int u) { rv[u] ^= 1, swap(lc, rc); }
inline void pd(int u) { if(rv[u]) Rev(lc), Rev(rc), rv[u] = 0; }
void rotate(int u) {
int y = fa[u], z = fa[y], k = ch[1][y] == u, w = ch[k ^ 1][u];
if(nroot(y)) ch[ch[1][z] == y][z] = u; ch[k][y] = w, ch[k ^ 1][u] = y;
if(w) fa[w] = y; fa[u] = z, fa[y] = u;
}
void splay(int u) {
int y = u, z; for(sta[top = 1] = y; nroot(y); sta[++top] = y = fa[y]);
for(; top; pd(sta[top--]));
for(; nroot(u); rotate(u)) {
y = fa[u], z = fa[y];
if(nroot(y)) rotate((ch[0][y] == u) ^ (ch[0][z] == y) ? u : y);
}
}
inline void access(int u) {
for(int y = 0; u; u = fa[y = u]) splay(u), rc = y;
}
inline void makeroot(int u) { access(u), splay(u), Rev(u); }
inline void split(int x, int y) { makeroot(x), access(y), splay(y); }
inline int findroot(int u) {
access(u), splay(u); for(; lc; pd(u), u = lc); splay(u); return u;
}
inline void lnk(int x, int y) { makeroot(x), fa[x] = y; }
inline void cut(int x, int y) { split(x, y), fa[x] = ch[0][y] = 0; }
void pushup(int u) {
sum[u] = 0, tr[u] = Min(tr[u * 2], tr[u * 2 + 1]);
if(tr[u] == tr[u * 2]) sum[u] += sum[u * 2];
if(tr[u] == tr[u * 2 + 1]) sum[u] += sum[u * 2 + 1];
}
void pushdown(int u) {
if(!lz[u]) return ;
lz[u * 2] += lz[u], lz[u * 2 + 1] += lz[u];
tr[u * 2] += lz[u], tr[u * 2 + 1] += lz[u];
lz[u] = 0;
}
void build(int u, int l, int r) {
tr[u] = 0, sum[u] = r - l + 1; if(l >= r) return ;
int mid = (l + r) >> 1;
build(u * 2, l, mid), build(u * 2 + 1, mid + 1, r);
}
void mdy(int u, int l, int r, int L, int R, int w) {
if(L <= l && r <= R) { tr[u] += w, lz[u] += w; return ; }
int mid = (l + r) >> 1; pushdown(u);
if(L <= mid) mdy(u * 2, l, mid, L, R, w);
if(R > mid) mdy(u * 2 + 1, mid + 1, r, L, R, w);
pushup(u);
}
void ask(int u, int l, int r, int L, int R) {
if(L <= l && r <= R) {
if(fst > tr[u]) fst = tr[u], snd = 0; if(fst == tr[u]) snd += sum[u];
return ;
}
int mid = (l + r) >> 1; pushdown(u);
if(L <= mid) ask(u * 2, l, mid, L, R);
if(R > mid) ask(u * 2 + 1, mid + 1, r, L, R);
}
bool check() {
static int tmp[5]; int len = 0;
for(int i = 0; i <4; i++) {
int x = idx[rb + 1] + dir[i][0], y = idy[rb + 1] + dir[i][1];
if(!x || !y || x > n || y > m || a[x][y] rb)
continue;
tmp[++len] = findroot(a[x][y]);
}
sort(tmp + 1, tmp + len + 1);
for(int i = 1; i return 1;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++)
scanf("%d", &a[i][j]), idx[a[i][j]] = i, idy[a[i][j]] = j;
build(1, 1, n * m), mdy(1, 1, n * m, 1, 1, 1);
for(; rb for(; lb int x = idx[lb] + dir[i][0], y = idy[lb] + dir[i][1];
if(!x || !y || x > n || y > m || a[x][y] rb)
continue;
cut(lb, a[x][y]);
}
++rb, mdy(1, 1, n * m, lb, rb, 1);
for(int i = 0; i <4; i++) {
int x = idx[rb] + dir[i][0], y = idy[rb] + dir[i][1];
if(!x || !y || x > n || y > m || a[x][y] rb)
continue;
lnk(rb, a[x][y]), mdy(1, 1, n * m, lb, a[x][y], -1);
}
fst = M, snd = 0, ask(1, 1, n * m, lb, rb); if(fst == 1) ans += snd;
}
printf("%I64d\n", ans);
return 0;
}


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
author-avatar
晴初沉浮的思念
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有