考场上没有认真审题,没有看到该题目的特殊之处:

保证每一行和每一列都恰有一只军队,即每一个Xi和每一个Yi都是不一样 的。

于是无论如何也想不到复杂度小于$O(n^3)$的算法,

只好打一个二维前缀和草草了事。

所以还是要仔细审题。

$O(n^2)$算法:

因为每行上只有一个军队,每列上仅有一个军队,

我们发现一个性质,如果记录上每行军队的列数,设h(x)表示第x行军队所在列,

一个$x->y$方案是合法的当且仅当$y-x=max(h(i))-min(h(i))$   $i \in [x,y]$,

枚举左右端点,记录已有的信息即可$O(1)$判断每个区间是否合法。

问题被我们转化为在一个数组a中,寻找符合$y-x=max(h(i))-min(h(i))$   $i \in [x,y]$的方案个数。

一种解决方法是分治

在分治的过程中,答案共来自三部分,

1.方案区间不涵盖中点的,递归向下处理。

对于涵盖中点的,先预处理出从中点到l,r的最大值和最小值。

2.方案区间最大值最小值均在一侧的:

以都在左侧为例。

我们从中点扫向左侧过程中,

对于每个点,都尝试使$mx[i]-mn[i]=p-i \Leftrightarrow p=mx[i]-mn[i]+i$满足,

通过预处理的mx和mn,判断该区间是否合法即可

3.方案区间最大值最小值分在左右的:

以左侧最小值,右侧最大值为例。

设k在左侧,i在右侧

如果使一个方案成立,我们需要满足三个条件:

$mx[i]-mn[k]=k-i \Leftrightarrow mx[i]+i=mn[k]+k ---① \\ mx[i]>mx[k] ---② \\ mn[i]>mn[k]---③ $

使k从中点向左移动,我们发现决策区间的左右端点是单调的,

注意到mn和mx绝对是单调的,

mn[k]不断减小,存在右端点以右的点符合条件2,

有更多的右区间符合条件2,则我们的右端点随之可以向右运动。

mx[k]不断增大,我们要使决策区间的左端点向右,

使至少满足条件3,则我们的左端点随之向右移动。

通过1式,我们可以把等号左侧放进一个桶里,随时维护合法决策区间,不断在桶中以等号右侧寻找答案即可。

但是对于左大右小的方案,桶中存在负数域,但能保证这个负数不会小于-n,

一个很好的解决方法是将桶数组翻3倍,建立一个指针指向桶数组的第n个点

可以直接访问指针的下标,原本的负数域被压到了正数,问题得到了解决。

 #include<iostream>
#include<cstdio>
using namespace std;
const int N=;
int n,x[N],b[N*],*bk=b+N,mx[N],mn[N];
int solve(int l,int r)
{
if(l==r) return ;
int ans=,mid=(l+r)>>;
ans+=solve(l,mid); ans+=solve(mid+,r);
mx[mid+]=mn[mid+]=x[mid+]; mx[mid]=mn[mid]=x[mid];
for(int i=mid+;i<=r;i++) mx[i]=max(mx[i-],x[i]),mn[i]=min(mn[i-],x[i]);
for(int i=mid-;i>=l;i--) mx[i]=max(mx[i+],x[i]),mn[i]=min(mn[i+],x[i]);//pre
for(int i=mid;i>=l;i--)
{
int p=mx[i]-mn[i]+i;
if(p>mid&&p<=r&&mx[i]>mx[p]&&mn[i]<mn[p]) ans++;
}//最值在左
for(int i=mid+;i<=r;i++)
{
int p=i-mx[i]+mn[i];
if(p>=l&&p<=mid&&mx[i]>mx[p]&&mn[i]<mn[p]) ans++;
}//最值在右
int i=mid+,j=mid+;
for(int k=mid;k>=l;k--)
{
while(mn[j]>mn[k]&&j<=r) bk[mx[j]-j]++,j++;
while(mx[i]<mx[k]&&i<j ) bk[mx[i]-i]--,i++;
ans+=bk[mn[k]-k];
}
while(i<j) bk[mx[i]-i]--,i++;//左小右大
i=mid,j=mid;
for(int k=mid+;k<=r;k++)
{
while(mn[j]>mn[k]&&j>=l) bk[mx[j]+j]++,j--;
while(mx[i]<mx[k]&&i>j ) bk[mx[i]+i]--,i--;
ans+=bk[mn[k]+k];
}
while(i>j) bk[mx[i]+i]--,i--;//左大右小
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=,a,b;i<=n;++i)
{
scanf("%d%d",&a,&b);
x[a]=b;
}
printf("%d\n",solve(,n));
return ;
}

奇袭 CodeForces 526F Pudding Monsters 题解的更多相关文章

  1. Codeforces 526F Pudding Monsters - CDQ分治 - 桶排序

    In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...

  2. Codeforces 526F Pudding Monsters

    先把题目抽象一下: 有一个静态的数组,求有多少个区间[i,j]满足:j-i==max{ai,...,aj}-min{ai,...,aj} 也就是要求max-min+i-j==0的区间数 所以肿么做呢? ...

  3. Codeforces 436D Pudding Monsters

    题意简述 开始有无限长的一段格子,有n个格子种有布丁怪兽,一开始连续的布丁怪兽算一个布丁怪兽. 每回合你可以将一个布丁怪兽向左或右移动,他会在碰到第一个布丁怪兽时停下,并与其合并. 有m个特殊格子,询 ...

  4. Codeforces 436D - Pudding Monsters(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 这题数据范围有点迷惑啊--乍一看 \(\mathcal O(nm)\) 过不去,还以为是正解是 \(\mathcal O(n+m ...

  5. 【CF526F】Pudding Monsters cdq分治

    [CF526F]Pudding Monsters 题意:给你一个排列$p_i$,问你有对少个区间的值域段是连续的. $n\le 3\times 10^5$ 题解:bzoj3745 Norma 的弱化版 ...

  6. [Codeforces526F]Pudding Monsters 分治

    F. Pudding Monsters time limit per test 2 seconds memory limit per test 256 megabytes In this proble ...

  7. 「CF526F」 Pudding Monsters

    CF526F Pudding Monsters 传送门 模型转换:对于一个 \(n\times n\) 的棋盘,若每行每列仅有一个棋子,令 \(a_x=y\),则 \(a\) 为一个排列. 转换成排列 ...

  8. Codeforces Round #543 Div1题解(并不全)

    Codeforces Round #543 Div1题解 Codeforces A. Diana and Liana 给定一个长度为\(m\)的序列,你可以从中删去不超过\(m-n*k\)个元素,剩下 ...

  9. Codeforces Round #545 Div1 题解

    Codeforces Round #545 Div1 题解 来写题解啦QwQ 本来想上红的,结果没做出D.... A. Skyscrapers CF1137A 题意 给定一个\(n*m\)的网格,每个 ...

随机推荐

  1. 在浏览器中输入 url 地址到显示主页的过程

    总体来说分为以下几个过程:1. DNS 解析2. TCP 连接3. 发送 HTTP 请求4. 服务器处理请求并返回 HTTP 报文5. 浏览器解析渲染页面6. 连接结束

  2. MAC电脑下Appium + python3 + robotframework ios的真机测试环境搭建

    本人的环境搭建前的准备,MAC电脑一台(macOS Mojave 10.14.0及以上),Xcode 10.0及以上   ,自己注册的一个Apple ID 账户,必须你的电脑能连接互联网,最好不要用公 ...

  3. 阿里巴巴Java开发手册更新了!

    自2017年,<阿里巴巴Java开发手册>发布,现已有超过260万位工程师下载及查阅手册,在数以千计的企业应用,手册成为受业界认可的开发规范. 昨天,<Java开发手册>再次更 ...

  4. C++ 中的静态成员函数与静态成员变量

    于CSDN 2014-01-17 与静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分.如果要在类外调用公用的静态成员函数,要用类名和域运算符"∷".如Box∷volu ...

  5. 【转载】C#通过Remove方法移除DataTable中的某一列数据

    在C#中的Datatable数据变量的操作过程中,有时候我们需要移除当前DataTable变量中的某一列的数据,此时我们就需要使用到DataTable变量内部的Columns属性变量的Remove方法 ...

  6. Spring容器的refresh()介绍

    Spring容器的refresh()[创建刷新]; 1.prepareRefresh()刷新前的预处理; 1).initPropertySources()初始化一些属性设置;子类自定义个性化的属性设置 ...

  7. select用法 多并发处理

    select默认最大检查套接口数量是1024,有定义 #define __NFDBITS (8 * sizeof(unsigned long)) #define __FD_SETSIZE 1024 # ...

  8. Java集合学习(4):HashTable

    一.概述 和HashMap一样,Hashtable也是一个散列表,它存储的内容是键值对. Hashtable在Java中的定义为: public class Hashtable<K,V> ...

  9. C#-Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046}

    异常信息如下 捕获到执行这句时异常: Excel.Application ep = new Excel.ApplicationClass(); Retrieving the COM class fac ...

  10. Nexus安装和使用

    1.前言 最近项目需要搭建maven私服,方便管理后期团队成员使用上传自己的包,因此决定使用nexus来搭建私服,搭建好的nexus地址. 2.准备工作 阿里云服务器ECS一台 1核CPU 2G内存( ...