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 }

 

posted @ 2017-09-08 17:40  Forever_goodboy  阅读(230)  评论(0编辑  收藏  举报