【NOIP提高】奇袭
来源:互联网 发布:2016网络作家富豪榜 女 编辑:程序博客网 时间:2024/05/16 04:55
Description
由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上要迎来最终的压力测试——魔界入侵。
唯一一个神一般存在的Administrator被消灭了,靠原本的整合骑士的力量是远远不够的。所以爱丽丝动员了UW全体人民,与整合骑士一起抗击魔族。
在UW的驻地可以隐约看见魔族军队的大本营。整合骑士们打算在魔族入侵前发动一次奇袭,袭击魔族大本营!
为了降低风险,爱丽丝找到了你,一名优秀斥候,希望你能在奇袭前对魔族大本营进行侦查,并计算出袭击的难度。
经过侦查,你绘制出了魔族大本营的地图,然后发现,魔族大本营是一个N×N的网格图,一共有N支军队驻扎在一些网格中(不会有两只军队驻扎在一起)。
在大本营中,每有一个k×k(1≤k≤N)的子网格图包含恰好k支军队,我们袭击的难度就会增加1点。
现在请你根据绘制出的地图,告诉爱丽丝这次的袭击行动难度有多大。
Solution
一开始还以为是什么树套树什么的,结果打了个暴力,就不管了。
转化为序列上的问题
因为每行每列都 只会出现一个点,b[x][y]有点,那么a[x]=y。
一个k*k的正方形里面有一个点,就相当于一个长度为k的区间中最大值-最小值=k-1就合法。
怎么做——分治
线段树没有想出来n log n的方法。
想一想经典的方法,ans[l,r]=ans[l,mid-1]+ans[mid+1,r]+跨区间的答案。
问题就是跨区间的答案要怎么算。
跨区间怎么算
因为要跨区间,那么符合答案的一段区间的[l1,r1],l1∈[l,mid],r1∈[mid+1,r]
有四种情况:
1、最小值在左边,最大值在左边。
2、最小值在右边,最大值在右边。
3。最小值在左边,最大值在右边。
4、最小值在右边,最大值在左边。
这里只讨论情况1和情况3,因为情况2和4与1和3对称。
先处理两个数组,da[i],xiao[i]。因为要跨区间,所以如果区间的左端点是i∈[l,mid],那么最大值值在[i,mid]区间内的,所以da[i]在[l,mid]的值是
xiao[i]同理。
情况1:最小值在左边,最大值在左边。
枚举一个左端点j,假设有一个右端点i,因为最值在左边,那么满足i-j=da[j]-xiao[j],所以j可以算出来i=j+(da[j]-xiao[j]),那么只要满足左边的最小值<右边的最小值,左边的最大值>右边的最大值就好了(即da[j]>=da[i]&&xiao[j]<=xiao[i)。
情况3:最小值在左边,最大值在右边。
枚举一个左端点i,如果有一个右端点j,因为最小值在左边,最大值在右边,所以满足左边的最小值<右边的最小值,左边的最大值<右边的最大值。那么左端点固定,右端点就会有一段可行范围。
可行区间还要满足j-i=da[j]-xiao[i],转化一下变成j-da[j]=i-xiao[i],所以把所有在可行区间的j,用一个桶tong[j-da[j]]++,那么每次答案加上tong[i-xiao[i]]就好了,i-da[j]可能会变成负数,所以需要加上mid变成tong[i-xiao[i]+mid]。
枚举可行区间不用从头枚举如果i为左端点的可行区间是l[i],r[i],那么l[i+1]>=l[i],r[i+1]>=r[i],因为da[i]和xiao[i]满足单调性。
Code
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=500007;int i,j,k,l,t,n,m;long long ans;int a[maxn],da[maxn],xiao[maxn],tong[maxn];void solve(int l,int r){ if(l>r)return; int mid=(l+r)/2,i,j,k,t; da[mid]=xiao[mid]=a[mid]; da[mid+1]=xiao[mid+1]=a[mid+1]; fod(i,mid-1,l)da[i]=max(da[i+1],a[i]),xiao[i]=min(xiao[i+1],a[i]); fo(i,mid+2,r)da[i]=max(da[i-1],a[i]),xiao[i]=min(xiao[i-1],a[i]); fod(j,mid,l){ i=j+(da[j]-xiao[j]); if(i>=mid&&i<=r&&da[j]>=da[i]&&xiao[j]<=xiao[i])ans++; } fo(i,mid+1,r){ j=i-(da[i]-xiao[i]); if(j<=mid&&j>=l&&da[j]<=da[i]&&xiao[j]>=xiao[i])ans++; } k=t=mid+1; fod(i,mid,l){ while(t<=r&&xiao[t]>=xiao[i])tong[da[t]-t+mid]++,t++; while(k<t&&da[k]<=da[i])tong[da[k]-k+mid]--,k++; ans+=tong[xiao[i]-i+mid]; } fo(i,k,t-1)tong[da[i]-i+mid]--; k=t=mid; fo(i,mid+1,r){ while(k>=l&&xiao[k]>=xiao[i])tong[da[k]+k-mid]++,k--; while(t>k&&da[t]<=da[i])tong[da[t]+t-mid]--,t--; ans+=tong[xiao[i]+i-mid]; } fo(i,k+1,t)tong[da[i]+i-mid]--; solve(l,mid-1),solve(mid+1,r);}int main(){// freopen("fan.in","r",stdin); scanf("%d",&n); fo(i,1,n){ scanf("%d%d",&k,&l); a[k]=l; } solve(1,n); printf("%I64d\n",ans);}
- 【NOIP提高】奇袭
- 奇袭
- 【NOIP2016提高A组8.12】奇袭
- 【NOIP2016提高A组8.12】奇袭
- 4687. 【NOIP2016提高A组8.12】奇袭
- JZOJ 4687 奇袭【NOIP2016提高A组8.12】
- 【NOIP提高】钱仓
- 【NOIP提高】种树
- 【NOIP提高】自然数
- 【NOIP提高】礼物
- 【NOIP提高】通讯
- 【NOIP提高】Value
- 【NOIP提高】Binary
- NOIP提高模拟 Binary
- 【NOIP提高】公约数
- NOIP 提高 公约数
- 【NOIP提高】树上路径
- NOIP提高组 单峰
- poj 2449
- Leetcode 274. H-Index (Medium) (cpp)
- Java的native关键字
- POJ 2155 Matrix
- 嵌入式开发第26天(信号、system V IPC、内存映射)
- 【NOIP提高】奇袭
- 利用getLayoutParams()方法和setLayoutParams()方法
- 数据结构实验之二叉树一:树的同构
- java中static关键字
- 初始化顺序
- 我对积分的解释
- 猴王水果竞猜系统php版源码修改
- 为什么在VMWare的NAT模式下无法使用traceroute
- 进程间通信