CF1109F Sasha and Algorithm of Silence's Sounds LCT、线段树
构成一棵树可以分成两个限制:图不成环、图的点数-边数=1。
我们考虑枚举右端点\(r\)计算所有可能的左端点\(l\)的答案。我们先考虑第一个限制:图不成环。注意到当\(r\)确定的时候,满足这个条件的\(l\)一定是一段后缀。设\(p_r\)表示满足图不成环时最小的\(l\),还可以发现\(p_r\)是单调不降的。那么我们可以使用双指针维护,在\(r\)增加\(1\)的时候使用LCT维护\(p_r\)的值。
接下来在每一个\(p_r\)求完之后,考虑图的点数-边数=1的限制。每一次\(r\)增加\(1\)的时候,都会增加一些新的可能的边。找到在矩阵上与\(r\)相邻且值在\([l,r]\)内的元素,设其中某一个的元素值为\(x\),那么在\(l \leq x\)的时候边\((x,r)\)就会出现。我们可以使用线段树维护每一个左端点的点数-边数,每一次增加一些新点和新边就是前缀加减的过程。
最后我们需要查询线段树中值为\(1\)的数的个数。这在区间加法下似乎不太可做,但是注意到如果将不合法位置的值设为INF,那么线段树中\(1\)一定是最小值。所以就相当于是一个求区间最小值数量的问题,就可以使用线段树去做了。
#include<bits/stdc++.h>
using namespace std;
int read(){
int a = 0; char c = getchar(); bool f = 0;
while(!isdigit(c)){f = c == '-'; c = getchar();}
while(isdigit(c)){
a = a * 10 + c - 48; c = getchar();
}
return f ? -a : a;
}
#define id(i , j) ((i - 1) * M + j)
#define PII pair < int , int >
const int _ = 2e5 + 3 , dir[4][2] = {0,1,0,-1,1,0,-1,0};
int N , M , L = 1 , R , arr[_]; long long cnt; PII to[_];
namespace segt{
int mn[_ << 2] , cnt[_ << 2] , mrk[_ << 2];
#define mid ((l + r) >> 1)
#define lch (x << 1)
#define rch (x << 1 | 1)
void init(int x , int l , int r){mn[x] = 1e9; cnt[x] = r - l + 1; if(l != r){init(lch , l , mid); init(rch , mid + 1 , r);}}
void mark(int x , int val){mrk[x] += val; mn[x] += val;}
void down(int x){mark(lch , mrk[x]); mark(rch , mrk[x]); mrk[x] = 0;}
void up(int x){mn[x] = min(mn[lch] , mn[rch]); cnt[x] = (mn[x] == mn[lch]) * cnt[lch] + (mn[x] == mn[rch]) * cnt[rch];}
void modify(int x , int l , int r , int L , int R , int val){
if(l >= L && r <= R) return mark(x , val);
down(x);
if(mid >= L) modify(lch , l , mid , L , R , val);
if(mid < R) modify(rch , mid + 1 , r , L , R , val);
up(x);
}
}
namespace LCT{
int fa[_] , ch[_][2]; bool rmrk[_];
bool nroot(int x){return ch[fa[x]][0] == x || ch[fa[x]][1] == x;}
bool son(int x){return ch[fa[x]][1] == x;}
void mark(int x){rmrk[x] ^= 1; swap(ch[x][0] , ch[x][1]);}
void down(int x){if(rmrk[x]){mark(ch[x][0]); mark(ch[x][1]); rmrk[x] = 0;}}
void dall(int x){if(nroot(x)) dall(fa[x]); down(x);}
void rot(int x){
bool f = son(x); int y = fa[x] , z = fa[y] , w = ch[x][f ^ 1];
fa[x] = z; if(nroot(y)) ch[z][son(y)] = x;
fa[y] = x; ch[x][f ^ 1] = y;
ch[y][f] = w; if(w) fa[w] = y;
}
void splay(int x){dall(x); while(nroot(x)){if(nroot(fa[x])) rot(son(fa[x]) == son(x) ? fa[x] : x); rot(x);}}
void access(int x){for(int y = 0 ; x ; y = x , x = fa[x]){splay(x); ch[x][1] = y;}}
int fdrt(int x){access(x); splay(x); while(ch[x][0]) down(x = ch[x][0]); splay(x); return x;}
void mkrt(int x){access(x); splay(x); mark(x);}
void split(int x , int y){mkrt(x); access(y); splay(y);}
void link(int x , int y){mkrt(x); fa[x] = y;}
void cut(int x , int y){split(x , y); ch[y][0] = fa[x] = 0;}
}
void cut(){
PII pos = to[L]; segt::modify(1 , 1 , N * M , L , L , 1e9);
for(int i = 0 ; i < 4 ; ++i){
int x = pos.first + dir[i][0] , y = pos.second + dir[i][1];
if(x > 0 && x <= N && y > 0 && y <= M && LCT::fdrt(arr[id(x , y)]) == LCT::fdrt(L))
LCT::cut(arr[id(x , y)] , L);
}
++L;
}
void link(){
PII pos = to[R];
for(int i = 0 ; i < 4 ; ++i){
int x = pos.first + dir[i][0] , y = pos.second + dir[i][1];
if(x > 0 && x <= N && y > 0 && y <= M){
int t = arr[id(x , y)];
while(t >= L && LCT::fdrt(t) == LCT::fdrt(R)) cut();
if(t >= L && t <= R) LCT::link(t , R);
}
}
for(int i = 0 ; i < 4 ; ++i){
int x = pos.first + dir[i][0] , y = pos.second + dir[i][1];
if(x > 0 && x <= N && y > 0 && y <= M && arr[id(x , y)] >= L && arr[id(x , y)] <= R)
segt::modify(1 , 1 , N * M , 1 , arr[id(x , y)] , -1);
}
}
int main(){
N = read(); M = read(); segt::init(1 , 1 , N * M);
for(int i = 1 ; i <= N ; ++i) for(int j = 1 ; j <= M ; ++j) to[arr[id(i , j)] = read()] = PII(i , j);
while(++R <= N * M){
segt::modify(1 , 1 , N * M , R , R , -1e9);
segt::modify(1 , 1 , N * M , 1 , R , 1); link();
cnt += (segt::mn[1] == 1) * segt::cnt[1];
}
cout << cnt; return 0;
}
CF1109F Sasha and Algorithm of Silence's Sounds LCT、线段树的更多相关文章
- Codeforces Round #539 (Div. 1) 1109F. Sasha and Algorithm of Silence's Sounds LCT+线段树 (two pointers)
题解请看 Felix-Lee的CSDN博客 写的很好,不过最后不用判断最小值是不是1,因为[i,i]只有一个点,一定满足条件,最小值一定是1. CODE 写完就A,刺激. #include <b ...
- [CF1109F]Sasha and Algorithm of Silence's Sounds
题意 有一个\(n*m\)的网格,每个格子有一个数,为\(1\)~\(n * m\)的排列 一个区间\((1<=l<=r<=n*m)\)是好的,当且仅当:数值在该区间内的格子,构成一 ...
- CodeForces 1109F. Sasha and Algorithm of Silence's Sounds
题目简述:给定一个$n \times m$的二维矩阵$a[i][j]$,其中$1 \leq nm \leq 2 \times 10^5$,矩阵元素$1 \leq a[i][j] \leq nm$且互不 ...
- Codeforces 1109F - Sasha and Algorithm of Silence's Sounds(LCT)
Codeforces 题面传送门 & 洛谷题面传送门 讲个笑话,这题是 2020.10.13 dxm 讲题时的一道例题,而我刚好在一年后的今天,也就是 2021.10.13 学 LCT 时做到 ...
- Codeforces Round #539 (Div. 1) C. Sasha and a Patient Friend 动态开点线段树
题解看这里 liouzhou_101的博客园 更简洁的代码看这里: #include <bits/stdc++.h> using namespace std; typedef long l ...
- 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法
C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...
- E. Sasha and Array 矩阵快速幂 + 线段树
E. Sasha and Array 这个题目没有特别难,需要自己仔细想想,一开始我想了一个方法,不对,而且还很复杂,然后lj提示了我一下说矩阵乘,然后再仔细想想就知道怎么写了. 这个就是直接把矩阵放 ...
- codeforces 719E E. Sasha and Array(线段树)
题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...
- Yandex.Algorithm 2011 Round 1 D. Sum of Medians 线段树
题目链接: Sum of Medians Time Limit:3000MSMemory Limit:262144KB 问题描述 In one well-known algorithm of find ...
随机推荐
- 【LG2839】[国家集训队]middle
[LG2839][国家集训队]middle 题面 洛谷 题解 按照求中位数的套路,我们二分答案\(mid\),将大于等于\(mid\)的数设为\(1\),否则为\(-1\). 若一个区间和大于等于\( ...
- uni-app 图片上传实战
uni.uploadFile()将本地资源上传到开发者服务器客户端发起一个post请求content-type multipart/form-data 通过uni.chooseImage获取一个本地资 ...
- 无法导入cv2模块(Python 3.6)
C:\Users\leahj>C:\Users\leahj\AppData\Local\Programs\Python\Python36\Scripts\pip3 install cv2 Col ...
- HustOJ二次开发之隐藏菜单栏
通过关键搜索: find / -name *nav.php 出现如下结果:/home/judge/src/web/template/ie/nav.php/home/judge/src/web/temp ...
- Node.js之判断字符串中是否包含某个字符串
server.txt内容如下: 阿里云服务器 关于应用场景,就不多说了,字符串是不论是后端开发还是前端开发等,都是要经常打交道了. test.js(node.js代码,只要被本地装了node.js环境 ...
- Spring中@Bean与@Configuration
一.Spring中Bean及@Bean的理解[1] Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法: 一.Bean是啥 1.Java面向对象,对象有方 ...
- kotlin基础 字符串模板
${变量名} var tmp="字符串模板” print("今天学习${tmp}这个知识点")
- python开发笔记-pymsslq连接操作SqlServer数据库
1. 普通连接测试 官方文档样例:http://pymssql.org/en/latest/pymssql_examples.html pymssql模块使用指南:https://blog.csdn. ...
- setTimeout的小尴尬
我们都知道,alert这种内置弹框会阻塞后续代码执行: 之所以如此,就是因为JavaScript代码在浏览器中是单线程执行的.换句话说,浏览器中只有一个主线程负责运行所有JavaScript代码(不考 ...
- 数学黑洞:卡普雷卡尔常数的php算法实现
首先看一篇文章: 英国广播公司报道,6174乍看没什么奇特之处,但是,自从1949年以来,它一直令数学家.数字控抓狂.痴迷. 不管你挑的四位数是什么,早早晚晚你都会遇到6174:而且,遇到6174就只 ...