由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上 要迎来最终的压力测试——魔界入侵。
唯一一个神一般存在的Administrator被消灭了,靠原本的整合骑士的力量 是远远不够的。所以爱丽丝动员了UW全体人民,与整合骑士一起抗击魔族。
在UW的驻地可以隐约看见魔族军队的大本营。整合骑士们打算在魔族入侵前 发动一次奇袭,袭击魔族大本营!
为了降低风险,爱丽丝找到了你,一名优秀斥候,希望你能在奇袭前对魔族 大本营进行侦查,并计算出袭击的难度。
经过侦查,你绘制出了魔族大本营的地图,然后发现,魔族大本营是一个N ×N的网格图,一共有N支军队驻扎在一些网格中(不会有两只军队驻扎在一起)。
在大本营中,每有一个k×k(1≤k≤N)的子网格图包含恰好k支军队,我们袭 击的难度就会增加1点。
现在请你根据绘制出的地图,告诉爱丽丝这次的袭击行动难度有多大。
第一行,一个正整数N,表示网格图的大小以及军队数量。
接下来N行,每行两个整数,Xi,Yi,表示第i支军队的坐标。
保证每一行和每一列都恰有一只军队,即每一个Xi和每一个Yi都是不一样 的。

1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #define Re register
7 using namespace std;
8 int read()
9 {
10 int f=1,x=0;char ch=getchar();
11 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
12 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
13 return f*x;
14 }
15 const int maxn=50005;
16 int n,a[maxn],ans;
17 int lmax[maxn],lmin[maxn],rmax[maxn],rmin[maxn],t[2*maxn];
18 void work(int l,int r,int mid)
19 {
20 lmax[mid]=lmin[mid]=a[mid];
21 rmax[mid+1]=rmin[mid+1]=a[mid+1];
22 for(int i=mid-1;i>=l;i--)
23 {
24 lmax[i]=max(lmax[i+1],a[i]);
25 lmin[i]=min(lmin[i+1],a[i]);
26 }
27 for(int i=mid+2;i<=r;i++)
28 {
29 rmax[i]=max(rmax[i-1],a[i]);
30 rmin[i]=min(rmin[i-1],a[i]);
31 }
32 //both left
33 for(int i=l;i<=mid;i++)
34 {
35 int j=i+lmax[i]-lmin[i];
36 if(j>mid&&j<=r)
37 if(lmax[i]>rmax[j]&&lmin[i]<rmin[j]) //由于左右两个区间必定不会有相等的元素,所以不用考虑等号
38 ans++;
39 }
40 //min is on left ,max is on right
41 int L=mid+1,R=mid+1;
42 while(L<=r&&lmax[l]>rmax[L])
43 {
44 t[rmax[L]-L+n]--;//走过的路径是不合法的
45 L++;
46 }
47 while(R<=r&&lmin[l]<rmin[R])
48 {
49 t[rmax[R]-R+n]++;//走过的路径都是合法的
50 R++;
51 }
52 for(int i=l;i<=mid;i++)//i从l向mid移动,lmin变大,lmax变小,使得LR能向左移动
53 {
54 while(L>mid+1&&lmax[i]<rmax[L-1])//当L==mid+1时,退出循环
55 {
56 L--;
57 t[rmax[L]-L+n]++;
58 }
59 while(R>mid+1&&lmin[i]>rmin[R-1])
60 {
61 R--;
62 t[rmax[R]-R+n]--;
63 }
64 if(t[lmin[i]-i+n]>0)
65 ans+=t[lmin[i]-i+n];
66 }
67 for(int i=mid+1;i<=r;i++)
68 t[rmax[i]-i+n]=0;
69 }
70 void divide(int l,int r)
71 {
72 if(l==r)
73 {
74 ans++;
75 return;
76 }
77 int mid=(l+r)>>1;
78 divide(l,mid);
79 divide(mid+1,r);
80 work(l,r,mid);
81 reverse(a+l,a+r+1);
82 if(((r-l)%2)==0) mid--;//1 2 3 4 5 交换后 5 4 3 2 1 仍然应该使123在一个区间所以 mid--;
83 work(l,r,mid);
84 reverse(a+l,a+r+1);
85 }
86 int main()
87 {
88 n=read();
89 for(int i=1;i<=n;i++)
90 {
91 int x,y;
92 x=read();y=read();
93 a[x]=y;
94 }
95 divide(1,n);
96 printf("%d",ans);
97 }
View Code

1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #define Re register
7 using namespace std;
8 int read()
9 {
10 int f=1,x=0;char ch=getchar();
11 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
12 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
13 return f*x;
14 }
15 const int maxn=50005;
16 int n,a[maxn],ans;
17 int lmax[maxn],lmin[maxn],rmax[maxn],rmin[maxn],t[2*maxn];
18 void work(int l,int r,int mid)
19 {
20 lmax[mid]=lmin[mid]=a[mid];
21 rmax[mid+1]=rmin[mid+1]=a[mid+1];
22 for(int i=mid-1;i>=l;i--)
23 {
24 lmax[i]=max(lmax[i+1],a[i]);
25 lmin[i]=min(lmin[i+1],a[i]);
26 }
27 for(int i=mid+2;i<=r;i++)
28 {
29 rmax[i]=max(rmax[i-1],a[i]);
30 rmin[i]=min(rmin[i-1],a[i]);
31 }
32 //both left
33 for(int i=l;i<=mid;i++)
34 {
35 int j=i+lmax[i]-lmin[i];
36 if(j>mid&&j<=r)
37 if(lmax[i]>rmax[j]&&lmin[i]<rmin[j]) //由于左右两个区间必定不会有相等的元素,所以不用考虑等号,下面同理
38 ans++;
39 }
40 //min is on left ,max is on right
41 int L=mid+1,R=mid+1;
42 for(int i=mid;i>=l;i--)//i从mid向l移动,lmin变小,lmax变大,使得LR能向向右移动
43 {
44 while(L<=r&&lmax[i]>rmax[L])//属于不合法的部分
45 {
46 t[rmax[L]-L+n]--;
47 L++;
48 }
49 while(R<=r&&lmin[i]<rmin[R])//
50 {
51 t[rmax[R]-R+n]++;//合法的
52 R++;
53 }
54 if(t[lmin[i]-i+n]>0)
55 ans+=t[lmin[i]-i+n];
56 }
57 for(int i=mid+1;i<=r;i++)
58 t[rmax[i]-i+n]=0;
59 }
60 void divide(int l,int r)
61 {
62 if(l==r)
63 {
64 ans++;
65 return;
66 }
67 int mid=(l+r)>>1;
68 divide(l,mid);
69 divide(mid+1,r);
70 work(l,r,mid);
71 reverse(a+l,a+r+1);
72 if(((r-l)%2)==0) mid--;//1 2 3 4 5 交换后 5 4 3 2 1 仍然应该使123在一个区间所以 mid--;
73 work(l,r,mid);
74 reverse(a+l,a+r+1);
75 }
76 int main()
77 {
78 n=read();
79 for(int i=1;i<=n;i++)
80 {
81 int x,y;
82 x=read();y=read();
83 a[x]=y;
84 }
85 divide(1,n);
86 printf("%d",ans);
87 }
View Code