非确定性有穷状态决策自动机练习题Vol.2 C. 奇袭
非确定性有穷状态决策自动机练习题Vol.2 C. 奇袭
题目描述
由于各种原因,桐人现在被困在\(Under World\)(以下简称\(UW\))中,而\(UW\)马上 要迎来最终的压力测试——魔界入侵。
唯一一个神一般存在的\(Administrator\)被消灭了,靠原本的整合骑士的力量 是远远不够的。所以爱丽丝动员了\(UW\)全体人民,与整合骑士一起抗击魔族。
在\(UW\)的驻地可以隐约看见魔族军队的大本营。整合骑士们打算在魔族入侵前 发动一次奇袭,袭击魔族大本营! 为了降低风险,爱丽丝找到了你,一名优秀斥候,希望你能在奇袭前对魔族大本营进行侦查,并计算出袭击的难度。
经过侦查,你绘制出了魔族大本营的地图,然后发现,魔族大本营是一个\(N \times N\)的网格图,一共有\(N\)支军队驻扎在一些网格中(不会有两只军队驻扎在一起)。
在大本营中,每有一个\(k×k(1≤k≤N)\)的子网格图包含恰好\(k\)支军队,我们袭 击的难度就会增加\(1\)点。
现在请你根据绘制出的地图,告诉爱丽丝这次的袭击行动难度有多大。
输入格式
第一行,一个正整数\(N\),表示网格图的大小以及军队数量。
接下来N行,每行两个整数,\(Xi\),\(Yi\),表示第\(i\)支军队的坐标。
保证每一行和每一列都恰有一只军队,即每一个\(Xi\)和每一个\(Yi\)都是不一样 的。
输出格式
一行,一个整数表示袭击的难度。
样例
样例输入
5
1 1
3 2
2 4
5 5
4 3
样例输出
10
样例解释
显然,分别以\((2,2)\)和\((4,4)\)为左上,右下顶点的一个子网格图中有\(3\)支军队,
这为我们的难度贡献了\(1\)点。
类似的子网格图在原图中能找出\(10\)个。
数据范围与提示
对于\(30\%\)的数据,\(N ≤ 100\)
对于\(60\%\)的数据,\(N ≤ 5000\)
对于\(100\%\)的数据,\(N ≤ 50000\)
分析
用线段树即可解决
首先,我们发现,如果要满足 \(k×k(1≤k≤N)\) 的子网格图包含恰好 \(k\) 支军队
那么这 \(k\) 只军队的最大横坐标减去最小横坐标恰好等于这 \(k\) 只军队的最大纵坐标减最小纵坐标
两维不好处理,因此我们把横坐标作为下标,纵坐标作为权值
这样原问题就变成了在一个排列中有多少区间内的数是连续的
我们发现这可以用线段树去维护
我们把线段树的节点定义为以某个点为左端点,以扫到的点为右端点的区间中连续区间的个数
线段树要维护的信息有连续区间个数的最小值,该最小值的个数,以及区间加和操作中的 \(lazy\) 标记
每次从右边新加入一个点 \(i\) 时,我们把区间 \([1,i]\) 整体加 \(1\)
代表此时又多了一个不连续的区间
此时我们去找 \(a[i]+1\) 和 \(a[i]-1\) 的位置,如果它们的位置在 \(i\) 的左边,我们就把 \([1,a[i]-1]\) 或者 \([1,a[i]+1]\) 整体减一,代表包含 \(a[i]+1\) 或者 \(a[i]-1\) 的区间可以与 \(a[i]\) 合并形成一个大区间
每次枚举一个右端点时就单独计算一下价值
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
const int maxn=1e6+5;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int a[maxn],n,wz[maxn];
struct asd{
int l,r,min,cnt,laz;
}tr[maxn<<1];
void push_up(int da){
if(tr[da<<1].min==tr[da<<1|1].min){
tr[da].min=tr[da<<1].min;
tr[da].cnt=tr[da<<1].cnt+tr[da<<1|1].cnt;
} else if(tr[da<<1].min<tr[da<<1|1].min){
tr[da].min=tr[da<<1].min;
tr[da].cnt=tr[da<<1].cnt;
} else {
tr[da].min=tr[da<<1|1].min;
tr[da].cnt=tr[da<<1|1].cnt;
}
}
void push_down(int da){
if(tr[da].laz==0) return;
tr[da<<1].min+=tr[da].laz;
tr[da<<1|1].min+=tr[da].laz;
tr[da<<1].laz+=tr[da].laz;
tr[da<<1|1].laz+=tr[da].laz;
tr[da].laz=0;
}
void build(int da,int l,int r){
tr[da].l=l,tr[da].r=r;
if(l==r){
tr[da].min=1;
tr[da].cnt=1;
return;
}
int mids=(l+r)>>1;
build(da<<1,l,mids);
build(da<<1|1,mids+1,r);
push_up(da);
}
int cx(int da,int l,int r){
if(tr[da].l>=l && tr[da].r<=r){
if(tr[da].min==1) return tr[da].cnt;
return 0;
}
push_down(da);
int mids=(tr[da].l+tr[da].r)>>1;
int ans=0;
if(l<=mids) ans+=cx(da<<1,l,r);
if(r>mids) ans+=cx(da<<1|1,l,r);
return ans;
}
void xg(int da,int l,int r,int val){
if(tr[da].l>=l && tr[da].r<=r){
tr[da].min+=val;
tr[da].laz+=val;
return;
}
push_down(da);
int mids=(tr[da].l+tr[da].r)>>1;
if(l<=mids) xg(da<<1,l,r,val);
if(r>mids) xg(da<<1|1,l,r,val);
push_up(da);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
int aa,bb;
aa=read(),bb=read();
a[aa]=bb;
wz[a[aa]]=aa;
}
build(1,1,n);
long long ans=0;
for(int i=1;i<=n;i++){
if(i>1) xg(1,1,i-1,1);
if(wz[a[i]-1]<=i && wz[a[i]-1]){
xg(1,1,wz[a[i]-1],-1);
}
if(wz[a[i]+1]<=i && wz[a[i]+1]){
xg(1,1,wz[a[i]+1],-1);
}
ans+=(long long)cx(1,1,i);
}
printf("%lld\n",ans);
return 0;
}
非确定性有穷状态决策自动机练习题Vol.2 C. 奇袭的更多相关文章
- 非确定性有穷状态决策自动机练习题Vol.1 A.扭动的回文串
非确定性有穷状态决策自动机练习题Vol.1 A.扭动的回文串 题目描述 \(JYY\)有两个长度均为\(N\)的字符串\(A\)和\(B\). 一个"扭动字符串\(S(i,j,k)\)由\( ...
- 非确定性有穷状态决策自动机练习题Vol.3 D. Dp搬运工3
非确定性有穷状态决策自动机练习题Vol.3 D. Dp搬运工3 题目描述 给定两个长度为 \(n\) 的排列,定义 \(magic(A,B)=∑_{i=1}^nmax(Ai,Bi)\) . 现在给定 ...
- [火星补锅] 非确定性有穷状态决策自动机练习题Vol.3 T3 && luogu P4211 [LNOI2014]LCA 题解
前言: 这题感觉还是很有意思.离线思路很奇妙.可能和二次离线有那么一点点相似?当然我不会二次离线我就不云了. 解析: 题目十分清真. 求一段连续区间内的所有点和某个给出的点的Lca的深度和. 首先可以 ...
- [火星补锅] 非确定性有穷状态决策自动机练习题Vol.1 T3 第K大区间 题解
前言: 老火星人了 解析: 很妙的二分题.如果没想到二分答案.. 很容易想到尝试用双指针扫一下,看看能不能统计答案. 首先,tail指针右移时很好处理,因为tail指针右移对区间最大值的影响之可能作用 ...
- goroutine 分析 协程的调度和执行顺序 并发写 run in the same address space 内存地址 闭包 存在两种并发 确定性 非确定性的 Go 的协程和通道理所当然的支持确定性的并发方式(
package main import ( "fmt" "runtime" "sync" ) const N = 26 func main( ...
- AC自动机练习题1:地图匹配
AC自动机板子,学习之前要是忘记了就看一下 1465: [AC自动机]地图匹配 poj1204 时间限制: 1 Sec 内存限制: 256 MB提交: 78 解决: 46[提交] [状态] [讨论 ...
- Vue兄弟组件(非父子组件)状态共享与传值
前言:网上大部分文章写的有点乱,很少有讲得易懂的文章. 所以,我写了篇在我能看得懂的基础上又照顾到大家的文章 =.= 作者:X1aoYE 备注:此文原创,转载请注明~ 内容里的<br> ...
- 非确定性计算引擎转化为C#版本并重构
这是之前我写的原始的 VB.NET 版本: http://www.cnblogs.com/RChen/archive/2010/05/17/1737587.html 转化为 C# 版本后,还进行了一些 ...
- 小白算法之路-非确定性多项式(non-deterministic polynomial,缩写NP)
前端小白的算法之路 时隔多日终于解决了埋在心头的一道难题,霎时云开雾散,今天把一路而来碰到的疑惑和心得都记录下来,也算是开启了自己探索算法的大门. 问题背景 曾经有一个年少轻狂的职场小白,在前端圈 ...
随机推荐
- @Autowired还可以注入List和Map
@LoadBalanced@Autowired(required = false)private List<RestTemplate> restTemplates = Collection ...
- NoSQL和SQL怎么选用?
NoSQL 有分很多种,其中key-value NoSQL (Redis, MemcacheD, etc) 的选用相对比较清楚些,大多是当后端Data storage的cache层来用.这篇主要想请教 ...
- 常见的HTTP返回状态值
200 (成功) 服务器已成功处理了请求. 通常,这表示服务器提供了请求的网页. 301 (永久移动) 请求的网页已永久移动到新位置. 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自 ...
- 《笨办法学 Python(第四版)》高清PDF|百度网盘免费下载|Python编程
<笨办法学 Python(第四版)>高清PDF|百度网盘免费下载|Python编程 提取码:jcl8 笨办法学 Python是Zed Shaw 编写的一本Python入门书籍.适合对计算机 ...
- 油田问题 bfs
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<time.h> #in ...
- Python for循环通过序列索引迭代
Python for 循环通过序列索引迭代: 注:集合 和 字典 不可以通过索引进行获取元素,因为集合和字典都是无序的. 使用 len (参数) 方法可以获取到遍历对象的长度. 程序: strs = ...
- Tkinter经典写法
1.继承 tkinter.Frame 类,实现类的基本写法 2.创建主窗口及主窗口大小位置及标题 3.将需要添加的组件放入到类中进行创建, 继承的 Frame 类需要使用 master 参数作为父类的 ...
- 《Python测试开发技术栈—巴哥职场进化记》—初来乍到,请多关照
上文<巴哥职场进化记-Python测试开发技术栈>开篇讲到巴哥毕业初到深圳,见到了来自五湖四海的室友.一番畅聊之后,抱着对未来职场生活的期待,大家都进入了梦乡.今天我们来看看巴哥第一天上班 ...
- PHP array_uintersect_uassoc() 函数
实例 比较两个数组的键名和键值(使用用户自定义函数进行比较),并返回交集: <?phpfunction myfunction_key($a,$b){if ($a===$b){return 0;} ...
- UOJ #310 黎明前的巧克力 FWT dp
LINK:黎明前的巧克力 我发现 很多难的FWT的题 都和方程有关. 上次那个西行寺无余涅槃 也是各种解方程...(不过这个题至今还未理解. 考虑dp 容易想到f[i][j][k]表示 第一个人得到巧 ...