codforces 奇袭
奇袭
时间限制: 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
solution:
转自http://blog.csdn.net/lyd_7_29/:
这题乍一看只能暴力啊!
但是有一个非常好的特性,保证每一行和每一列都恰有一只军队 这意味着什么? 我们可以看成是一维的,第i行的军队所在的列作为一维中数组第i个位置的值。 那么什么恰好k个在正方形里面就是序列上连续的一段[l,r]的max(l,r)-min(l,r)=r-l 这个可以暴力,是O(n2)的,可以拿70分。
满分做法需要用分治,分而治之。 我们可以分2种情况讨论: 1.最小值和最大值在同侧。 2.最小值和最大值在异侧。 稍微思考一下,其实都很好判断。 主要是第2种麻烦一些。 假设最小值在左侧,最大值在右侧,如果一个区间满足我们所要求的关系的话,就一定有: max(a[mid+1]…a[r])-min(a[l]…a[mid])=r-l 移项可得 max(a[mid+1]…a[r])-r=min(a[l]…a[mid])-l 这个用两个指针分别指一指指出对于合法的位置的范围,用桶记录弄一下。(这题可以用选段树,不过本菜鸟不太会)。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 #define pp 100000 7 int read() { 8 int s=0,f=1; 9 char ch=getchar(); 10 for( ; ch<'0'||ch>'9'; f=(ch=='-')?(-1):(f),ch=getchar()) ; 11 for( ; ch>='0'&&ch<='9'; s=(s<<1)+(s<<3)+(ch^48),ch=getchar()) ; 12 return s*f; 13 } 14 int n; 15 struct mapp { 16 int x,y; 17 friend bool operator < (mapp a,mapp b) { 18 return a.y<b.y; 19 } 20 } c[50001]; 21 int ji[50001],mnl[50002],mxl[50002],mnr[50002],mxr[50002],tong[200005]; 22 void init(int l,int r) { 23 int mid=(l+r)>>1; 24 mnl[mid+1]=0x7fffffff; 25 mnr[mid]=0x7fffffff; 26 mxl[mid+1]=-0x7fffffff; 27 mxr[mid]=-0x7fffffff; 28 for(int i=mid; i>=l; --i) { 29 mnl[i]=min(mnl[i+1],c[i].x); 30 mxl[i]=max(mxl[i+1],c[i].x); 31 } 32 for(int i=mid+1; i<=r; ++i) { 33 mnr[i]=min(mnr[i-1],c[i].x); 34 mxr[i]=max(mxr[i-1],c[i].x); 35 } 36 } 37 int two_divi(int l,int r) { 38 if(l==r) { 39 return 1; 40 } 41 int mid=(l+r)>>1,ans=0; 42 ans+=two_divi(l,mid)+two_divi(mid+1,r); 43 init(l,r); 44 for(int i=l; i<=mid; ++i) { 45 int j=i+(mxl[i]-mnl[i]); 46 if(mnl[i]>mnr[j]||mxl[i]<mxr[j]) { 47 continue; 48 } 49 if(j<=r&&j>=mid+1) { 50 ++ans; 51 } 52 } 53 for(int i=mid+1; i<=r; ++i) { 54 int j=i-(mxr[i]-mnr[i]); 55 if(mnr[i]>mnl[j]||mxr[i]<mxl[j]) { 56 continue; 57 } 58 if(l<=j&&j<=mid) { 59 ++ans; 60 } 61 } 62 int st=mid+1,ed=mid; 63 for(int i=mid; i>=l; --i) { 64 while(mnr[ed+1]>mnl[i]&&ed<r) { 65 ++ed; 66 ++tong[mxr[ed]-ed+pp]; 67 } 68 while(mxl[i]>mxr[st]) { 69 --tong[mxr[st]-st+pp]; 70 ++st; 71 if(st>r) { 72 break; 73 } 74 } 75 if(st>r) { 76 break; 77 } 78 if(st<=ed) { 79 ans+=tong[mnl[i]-i+pp]; 80 } 81 } 82 for(int i=mid; i<=r; ++i) { 83 tong[mxr[i]-i+pp]=0; 84 } 85 for(int i=l; i<=mid; ++i) { 86 tong[mnl[i]-i+pp]=0; 87 } 88 st=mid,ed=mid+1; 89 for(int i=mid+1; i<=r; ++i) { 90 while(mnl[ed-1]>mnr[i]&&ed>l) { 91 --ed; 92 ++tong[mxl[ed]+ed+pp]; 93 } 94 while(mxr[i]>mxl[st]) { 95 --tong[mxl[st]+st+pp]; 96 --st; 97 if(st<l) { 98 break; 99 } 100 } 101 if(st<l) { 102 break; 103 } 104 if(ed<=st) { 105 ans+=tong[mnr[i]+i+pp]; 106 } 107 } 108 for(int i=l; i<=mid; ++i) { 109 tong[mxl[i]+i+pp]=0; 110 } 111 for(int i=mid+1; i<=r; ++i) { 112 tong[mnr[i]+i+pp]=0; 113 } 114 return ans; 115 } 116 int main() { 117 //freopen("raid9.in","r",stdin); 118 n=read(); 119 for(int x,y,i=1; i<=n; ++i) { 120 c[i]=(mapp) { 121 x=read(),y=read() 122 }; 123 } 124 sort(c+1,c+n+1); 125 for(int i=1; i<=n; ++i) { 126 ji[c[i].x]=i; 127 } 128 int ans=two_divi(1,n); 129 printf("%d\n",ans); 130 return 0; 131 }