问题 C: 奇袭

时间限制: 1 Sec  内存限制: 256 MB

题目描述

由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上 要迎来最终的压力测试——魔界入侵。

唯一一个神一般存在的Administrator被消灭了,靠原本的整合骑士的力量 是远远不够的。所以爱丽丝动员了UW全体人民,与整合骑士一起抗击魔族。

在UW的驻地可以隐约看见魔族军队的大本营。整合骑士们打算在魔族入侵前 发动一次奇袭,袭击魔族大本营!

为了降低风险,爱丽丝找到了你,一名优秀斥候,希望你能在奇袭前对魔族 大本营进行侦查,并计算出袭击的难度。

经过侦查,你绘制出了魔族大本营的地图,然后发现,魔族大本营是一个N ×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

  这道题当时看一眼还以为又是一个带权并查集的大坑,然后发现我只猜对了一半,这确实是个坑,不过貌似与带权并查集没啥关系。

  开始的时候先打了一个n^3 log(n^2)的树状数组暴力期望目测30分,然后又打了一个严格n^2的单调队列暴力55分(虽然我期望60),考完后惊喜的发现加了一些剪枝的n^2可以水到91分……

  这道题正解是线段树或分治,由于线段树打发我不会,我就只讲分治了。

  我们可以发现这道题有一个极其优美的性质即每行每列只有一个敌人也就意味着我们没有必要去管那些没有敌人的位置。然后让我们分析一下时间复杂度,他的最大解是1250025000(所有敌人排成一个对角线),显然直接枚举每一个解都会炸也就是说所有复杂度大于等于O(合法方块数量)的都挂了。这道题也显然没有O(1)做法,那我们该咋搞呢?

  我们可以发现,他是一个区间解,我们可以尝试一下分治这个本身时间复杂度为log n的想法,我们可以把每一个区间的解分成三个来源,左区间的解,右区间的解,区间跨过终点的解。很明显这三个不会重复,而且前两个直接就可以得到,难点在第三个来源上,对于第三个来源,我们又可以分为四种情况,区间最大值最小值在左侧(右侧),区间最大值在左(右),最小值在右(左),前两种我们可以通过类似于前缀后缀最大最小值的思想枚举左或右区间端点,然后O(1)的得到区间另一个端点,通过前后缀最大最小值是否合法判断是否算到答案之中,对于后两种就是本代码的核心了。

  我们先以最小值在左最大值在右为例讲解,首先满足要求的区间一定是这样的:

  max(a[mid +1]...a[right]) - min(a[left]...a[mid]) = right - left

  通过移项可知

  max(a[mid +1]...a[right]) - right = min(a[left]...a[mid]) - left

  然后我们可以发现等式两边就没有直接联系了,借助天天爱跑步的思路,桶,我们存下每一个rmax[i]-i的值然后枚举左端点就可以了。值得注意的是rmax,rmin,lmin,lmax,都是具有优美的单调性质的,我们可以利用这一点再剪一下枝,同时,由于桶的存在,我们也就避免了一个个的去统计所有解,明显加快了时间。

  对于最大值在左侧最小值在右侧我们只要转换一下就好了:

  max(a[mid +1]...a[right]) + right = min(a[left]...a[mid]) + left

  然后同理。

 #include<iostream>
 #include<cstdio>
 #include<cstdlib>
 #include<cstring>
 #include<cmath>
 #include<algorithm>
 #include<queue>
 #define N 50005
 using namespace std;
 +];
 int lmin[N],rmin[N],lmax[N],rmax[N];
 int work2(int l,int r,int mid)
 {
     lmin[mid]=lmax[mid]=a[mid];
     rmin[mid+]=rmax[mid+]=a[mid+];
     ;i>=l;i--)
     {
         lmin[i]=min(lmin[i+],a[i]);
         lmax[i]=max(lmax[i+],a[i]);
     }
     ;i<=r;i++)
     {
         rmin[i]=min(rmin[i-],a[i]);
         rmax[i]=max(rmax[i-],a[i]);
     }
     ;
     for(int i=l;i<=mid;i++)
     {
         int to=i+lmax[i]-lmin[i];
         if(to<=r&&to>mid&&rmax[to]<lmax[i]&&lmin[i]<rmin[to]) ans++;
     }
     ;i<=r;i++)
     {
         int to=i-rmax[i]+rmin[i];
         if(to>=l&&to<=mid&&rmax[i]>lmax[to]&&rmin[i]<lmin[to]) ans++;
     }
     ,q=mid+;
     while(p<=r&&rmin[p]>lmin[l])  //min is on the left
     {
         t[rmax[p]-p+N]++;
         p++;
     }
     while(q<=r&&rmax[q]<lmax[l])  //max is on the right
     {
         t[rmax[q]-q+N]--;
         q++;
     }
     for(int i=l;i<=mid;i++)
     {
         &&rmin[p-]<lmin[i])
         {
             p--;
             t[rmax[p]-p+N]--;
         }
         &&rmax[q-]>lmax[i])
         {
             q--;
             t[rmax[q]-q+N]++;
         }
         )
             ans+=t[lmin[i]-i+N];
     }
     ;i<=r;i++)t[rmax[i]-i+N]=;
     p=mid,q=mid;
     while(p>=l&&lmin[p]>rmin[r])//min is on the right
     {
         t[lmax[p]+p+N]++;
         p--;
     }
     while(q>=l&&lmax[q]<rmax[r]) //max is on the left
     {
         t[lmax[q]+q+N]--;
         q--;
     }
     for(int i=r;i>mid;i--)
     {
         ]<rmin[i])
         {
             p++;
             t[lmax[p]+p+N]--;
         }
         ]>rmax[i])
         {
             q++;
             t[lmax[q]+q+N]++;

         }
         )
         {
             ans+=t[rmin[i]+i+N];
         }
     }
     for(int i=l;i<=mid;i++)
     {
         t[lmax[i]+i+N]=;
     }
     return ans;
 }
 int work(int l,int r)
 {
     ;
     ;
     ,r);

     ans+=work2(l,r,mid);
     return ans;
 }
 int main()
 {
     scanf("%d",&n);
     ;i<=n;i++)
     {
         int x,y;
         scanf("%d%d",&x,&y);
         a[x]=y;
     }
     //cout<<endl;
     printf(,n));
     ;
 }

  其实还有一个黑科技 reverse函数将整个区间左右调换,省了不少代码量,只是复杂度多了一个log n。

 

 #include<iostream>
 #include<cstdio>
 #include<cstdlib>
 #include<cstring>
 #include<cmath>
 #include<algorithm>
 #include<queue>
 #define N 50005
 using namespace std;
 +];
 int lmin[N],rmin[N],lmax[N],rmax[N];
 int work2(int l,int r,int mid)
 {
     lmin[mid]=lmax[mid]=a[mid];
     rmin[mid+]=rmax[mid+]=a[mid+];
     ;i>=l;i--)
     {
         lmin[i]=min(lmin[i+],a[i]);
         lmax[i]=max(lmax[i+],a[i]);
     }
     ;i<=r;i++)
     {
         rmin[i]=min(rmin[i-],a[i]);
         rmax[i]=max(rmax[i-],a[i]);
     }
     ;
     for(int i=l;i<=mid;i++)
     {
         int to=i+lmax[i]-lmin[i];    //max,min is on the left
         if(to<=r&&to>mid&&rmax[to]<lmax[i]&&lmin[i]<rmin[to]) ans++;
     }
     ,q=mid+;
     while(p<=r&&rmin[p]>lmin[l])    //min is on the left
     {
         t[rmax[p]-p+N]++;
         p++;
     }
     while(q<=r&&rmax[q]<lmax[l])    //max is on the right
     {
         t[rmax[q]-q+N]--;
         q++;
     }
     for(int i=l;i<=mid;i++)
     {
         &&rmin[p-]<lmin[i])
         {
             p--;
             t[rmax[p]-p+N]--;
         }
         &&rmax[q-]>lmax[i])
         {
             q--;
             t[rmax[q]-q+N]++;
         }
         )
             ans+=t[lmin[i]-i+N];
     }
     ;i<=r;i++)t[rmax[i]-i+N]=;
     return ans;
 }
 int work(int l,int r)
 {
     ;
     ;
     ,r);
     ans+=work2(l,r,mid);
     reverse(a+l,a+r+);
     ans+=work2(l,r,mid-((r-l+)%));
     reverse(a+l,a+r+);
     return ans;
 }
 int main()
 {
     scanf("%d",&n);
     ;i<=n;i++)
     {
         int x,y;
         scanf("%d%d",&x,&y);
         a[x]=y;
     }
     printf(,n));
     ;
 }

9.5 考试 第三题 奇袭题解(codeforce 526f)的更多相关文章

  1. 9.18考试 第三题chess题解

    在讲这道题之前我们先明确一个丝薄出题人根本没有半点提示却坑死了无数人的注意点: 走敌人和不走敌人直接到时两种走法,但只走一个敌人和走一大坨敌人到同一个点只算一种方案(当然,前提是步骤一致). 当时看完 ...

  2. bzoj 2752 9.20考试第三题 高速公路(road)题解

    2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1545  Solved: 593[Submit] ...

  3. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  4. Codeforces Round #524 (Div. 2)(前三题题解)

    这场比赛手速场+数学场,像我这样读题都读不大懂的蒟蒻表示呵呵呵. 第四题搞了半天,大概想出来了,但来不及(中途家里网炸了)查错,于是我交了两次丢了100分.幸亏这次没有掉rating. 比赛传送门:h ...

  5. Lyft Level 5 Challenge 2018 - Final Round (Open Div. 2) (前三题题解)

    这场比赛好毒瘤哇,看第四题好像是中国人出的,怕不是dllxl出的. 第四道什么鬼,互动题不说,花了四十五分钟看懂题目,都想砸电脑了.然后发现不会,互动题从来没做过. 不过这次新号上蓝名了(我才不告诉你 ...

  6. PYC#1欢乐赛第三题题解

    这里是比赛地址:http://tieba.baidu.com/p/2859693237,果然参赛神牛汇集. 第三题题目大意如下: 已知n条二次函数曲线Si(x)=aix^2+bix+ci(ai> ...

  7. [考试]NOIP2015模拟题2

    // 此博文为迁移而来,写于2015年7月22日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w72i.html 1.总 ...

  8. C语言考试解答十题

    学院比较奇葩,大一下期让学的VB,这学期就要学C++了,然后在开学的前三个周没有课,就由老师讲三个周的C语言,每天9:30~11:30听课,除去放假和双休日,实际听课时间一共是12天*2小时,下午是1 ...

  9. CodeM美团点评编程大赛复赛 做题感悟&题解

    [T1] [简要题意]   长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...

随机推荐

  1. centos搭建免费的ssl证书,大部分浏览器均支持!(let’s encrypt 的使用记录)

    安装certbot wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto 然后就是通过这个脚本获取证书,安装前先将NGINX 停一下. ...

  2. 【全面解禁!真正的Expression Blend实战开发技巧】第十章 FluidMoveBehavior完全解析之三飞出ListBox吧

    原文:[全面解禁!真正的Expression Blend实战开发技巧]第十章 FluidMoveBehavior完全解析之三飞出ListBox吧 刚才有人说我的标题很给力,哈哈.那这个标题肯定更给力了 ...

  3. 图像滤镜艺术---流行艺术风滤镜特效PS实现

    原文:图像滤镜艺术---流行艺术风滤镜特效PS实现 今天,本人给大家介绍一款新滤镜:流行艺术风效果,先看下效果吧! 原图 流行艺术风效果图 上面的这款滤镜效果是不是很赞,呵呵,按照本人以往的逻辑,我会 ...

  4. docker启动命令,docker重启命令,docker关闭命令

    启动        systemctl start docker 守护进程重启   sudo systemctl daemon-reload 重启docker服务   systemctl restar ...

  5. 《KVM虚拟化技术实战和原理解析》读书笔记(十几篇)

    第一章和第二章 第一章 虚拟化和云计算 Saas(软件即服务):将已经部署好的软件作为一种服务来提供,比如:Google Docs, Google Apps Paas(平台即服务):将开发环境作为一种 ...

  6. Linux SD卡建立两个分区

    本文主要介绍Linux 环境下 SD 卡建立两个分区的操作流程: 操作环境:Linux Ubuntu 2016.4 操作目的:将 SD 卡分为两个分区:第一分区格式为 FAT32,大小 500M.第二 ...

  7. 剖析Qt的事件机制原理(源代码级别)

    在用Qt写Gui程序的时候,在main函数里面最后依据都是app.exec();很多书上对这句的解释是,使Qt程序进入消息循环.下面我们就到exec()函数内部,来看一下他的实现原理.Let's go ...

  8. .NET开发框架(一)-框架介绍与视频演示

    本文主要介绍一套基于.NET CORE的SPA高并发.高可用的开发框架. 我们暂且称它为:(让你懂.NET)开发框架. 以此为主线,陆续编写教程,讲述如何构建高并发.高可用的框架. (欢迎转载与分享) ...

  9. Git--将已有的项目添加到github

    (2). 初始化本地仓库,并提交内容到本地 需要先打开 命令行终端,然后通过 cd 命令切换到需要添加到github 的项目的目录下,然后依次执行如下命令, 具体命令及其含义如下: 1). touch ...

  10. 手把手docker部署java应用(初级篇)

    本篇原创发布于 Flex 的个人博客:点击跳转 前言   在没有 docker 前,项目转测试是比较麻烦的一件事.首先会化较长的时间搭建测试环境,然后在测试过程中又经常出现测试说是 bug,开发说无法 ...