#分治 or 线段树+单调栈#CF526F Pudding Monsters
题目
给定一个 \(n \times n\) 的棋盘,其中有 \(n\) 个棋子,每行每列恰好有一个棋子。
求有多少个 \(k \times k\) 的子棋盘中恰好有 \(k\) 个棋子。
分析
先将二维的棋子转换成一维的排列,也就是问有多少个区间 \([l,r]\) 满足 \(\max-\min=r-l\)
一种方法就是分治,分类讨论最大值最小值在哪边,同一边那么另外一个端点就可以确定,
否则用一个桶记录一下 \(\max-r\) 或者 \(\max+l\) 的个数,把不合法的删掉,这样就是一个 \(\log\)
另外一种方法是固定右端点,然后用单调栈维护后缀最大值和最小值并在线段树上实时修改,
观察到 \(\max-\min+l\geq r\),并且在 \(l=r\) 时必取得最小值 \(r\),那么也就是询问最小值个数,同样在线段树上维护,也是一个 \(\log\)
代码(分治)
#include <cstdio>
#include <cctype>
using namespace std;
const int N=300011; long long ans;
int mn[N],mx[N],a[N],n,c[N<<1];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
void dfs(int l,int r){
if (l==r) return;
int mid=(l+r)>>1;
mn[mid]=mx[mid]=a[mid];
mn[mid+1]=mx[mid+1]=a[mid+1];
for (int i=mid-1;i>=l;--i) mn[i]=min(mn[i+1],a[i]),mx[i]=max(mx[i+1],a[i]);
for (int i=mid+2;i<=r;++i) mn[i]=min(mn[i-1],a[i]),mx[i]=max(mx[i-1],a[i]);
for (int i=mid;i>=l;--i){
int j=mx[i]-mn[i]+i;
if (j>mid&&j<=r&&mx[i]>mx[j]&&mn[j]>mn[i]) ++ans;
}
for (int j=mid+1;j<=r;++j){
int i=j-mx[j]+mn[j];
if (l<=i&&i<=mid&&mn[i]>mn[j]&&mx[j]>mx[i]) ++ans;
}
int j=mid+1,k=mid+1;
for (int i=mid;i>=l;--i){
for (;j<=r&&mn[j]>mn[i];++j) ++c[mx[j]-j+n];
for (;k<j&&mx[k]<mx[i];++k) --c[mx[k]-k+n];
ans+=c[mn[i]-i+n];
}
for (int i=k;i<j;++i) --c[mx[i]-i+n];
j=mid+1,k=mid+1;
for (int i=mid;i>=l;--i){
for (;j<=r&&mx[j]<mx[i];++j) ++c[mn[j]+j];
for (;k<j&&mn[k]>mn[i];++k) --c[mn[k]+k];
ans+=c[mx[i]+i];
}
for (int i=k;i<j;++i) --c[mn[i]+i];
dfs(l,mid),dfs(mid+1,r);
}
int main(){
n=iut();
for (int i=1,x;i<=n;++i)
x=iut(),a[x]=iut();
dfs(1,n);
return !printf("%lld",ans+n);
}
代码(线段树)
#include <cstdio>
#include <cctype>
using namespace std;
const int N=300011,inf=0x3f3f3f3f; long long ans;
int st0[N],st1[N],Top0,Top1,w[N<<2],mn[N<<2],lazy[N<<2],n,a[N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void build(int k,int l,int r){
mn[k]=inf,w[k]=r-l+1;
if (l==r) return;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void update(int k,int l,int r,int x,int y,int z){
if (l==x&&r==y){
mn[k]+=z,lazy[k]+=z;
return;
}
int mid=(l+r)>>1;
if (lazy[k]){
mn[k<<1]+=lazy[k],mn[k<<1|1]+=lazy[k];
lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k];
lazy[k]=0;
}
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
if (mn[k<<1]<mn[k<<1|1]) mn[k]=mn[k<<1],w[k]=w[k<<1];
else mn[k]=mn[k<<1|1],w[k]=w[k<<1|1]+(mn[k<<1]==mn[k<<1|1])*w[k<<1];
}
int main(){
n=iut();
for (int i=1,x;i<=n;++i) x=iut(),a[x]=iut();
build(1,1,n);
for (int i=1;i<=n;++i){
for (;Top0&&a[st0[Top0]]<=a[i];--Top0)
update(1,1,n,st0[Top0-1]+1,st0[Top0],a[i]-a[st0[Top0]]);
for (;Top1&&a[st1[Top1]]>=a[i];--Top1)
update(1,1,n,st1[Top1-1]+1,st1[Top1],a[st1[Top1]]-a[i]);
st0[++Top0]=st1[++Top1]=i,update(1,1,n,i,i,i-inf);
ans+=w[1];
}
return !printf("%lld",ans);
}
#分治 or 线段树+单调栈#CF526F Pudding Monsters的更多相关文章
- Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)
Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...
- Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈
原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html 题目传送门 - CF781E 题意 有一个矩形,宽为 w ,高为 h .一开始会有 w 个 ...
- 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈
正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...
- 线段树+单调栈+前缀和--2019icpc南昌网络赛I
线段树+单调栈+前缀和--2019icpc南昌网络赛I Alice has a magic array. She suggests that the value of a interval is eq ...
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)
题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j< ...
- AtCoder Regular Contest 063 F : Snuke’s Coloring 2 (线段树 + 单调栈)
题意 小 \(\mathrm{C}\) 很喜欢二维染色问题,这天他拿来了一个 \(w × h\) 的二维平面 , 初始时均为白色 . 然后他在上面设置了 \(n\) 个关键点 \((X_i , Y_i ...
- [Codeforces1132G]Greedy Subsequences——线段树+单调栈
题目链接: Codeforces1132G 题目大意:给定一个序列$a$,定义它的最长贪心严格上升子序列为$b$满足若$a_{i}$在$b$中则$a_{i}$之后第一个比它大的也在$b$中.给出一个数 ...
- BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)
BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...
- 2018.09.22 atcoder Snuke's Coloring 2(线段树+单调栈)
传送门 就是给出一个矩形,上面有一些点,让你找出一个周长最大的矩形,满足没有一个点在矩形中. 这个题很有意思. 考虑到答案一定会穿过中线. 于是我们可以把点分到中线两边. 先想想暴力如何解决. 显然就 ...
随机推荐
- win32-LPCSTR->String
#include <string> void makebox(LPCSTR name) { std::string res(name); res += " is X"; ...
- 原来你是这样的JAVA--[07]聊聊Integer和BigDecimal
今天来聊聊Java中跟数值处理相关的两个类型Integer和BigDecimal. 说起这两个类型,我们肯定都不陌生,但是其中有些容易踩到的坑需要注意避让. Integer 整型我们应该每天都会用到, ...
- Thinkpad T14 AMD版无线网卡不可用
硬件环境: Thinkpad T14 AMD 操作系统: Windows 10家庭版 问题描述: Windows 10在后台默默做了补丁更新,导致无线网卡和蓝牙鼠标都不可用(但是有线网却是能正常工作的 ...
- 亲测可行,Android Studio 查看源码出现 Source for ‘Android API xxx Platform’ not found 的解决方法
亲测可行,Android Studio 查看源码出现 Source for 'Android API xxx Platform' not found 的解决方法 如标题中的问题,产生的原因就是 SDK ...
- 本机复制的内容粘贴不到VMware虚拟机里面的解决办法
分析 VMware正确安装完linux虚拟机之后,这里以Ubuntu为例,如果你使用的默认配置,正常情况下就可以复制.粘贴和拖拽内容的,双方向都是支持的.如果不能复制和拖拽一般是vmware tool ...
- 【MongoDB】MongoDB原理分析、集群搭建(Docker)与简单使用
一.MongoDB 简介 MongoDB是一个基于分布式文件存储的数据库,介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的.其目的是为WEB应用提供可扩展的高性能数据存 ...
- 服务网关ZUUL过滤器
过滤器两个功能: 1.其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础: 2.过滤器功能则负责对请求的处理过程进行预干预,是实现请求校验.服务聚合等功能的基础. 有4类 ...
- el-select封装(单选框、多选框、全选功能)
先看看设计图: 网上找了一溜,都是扯淡,样式也没个 自己动手吧,先把样式搞定 popper-class="xx-option" 所有单选框都用 :after和:before类 + ...
- map 简单梳理【GO 基础】
〇.map 简介 map 是一种无序的基于 key-value 的数据结构,Go 语言中的 map 是引用类型,必须初始化才能使用. 其中键可以是任何类型,但值必须是可比较的类型(如整数.字符串.布尔 ...
- get 加 header 下载文件 函数,虽然最后没用。
export const apiDown = (url, data = {}) => { let data2 = secretFilter(data) axiosDown({ url, para ...