• 模拟4题解 T3奇袭


    T3奇袭


    题目描述

    由于各种原因,桐人现在被困在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


     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
    愿你在迷茫时,记起自己的珍贵。
  • 相关阅读:
    利用Python进行数据分析_Pandas_绘图和可视化_Matplotlib
    利用Python进行数据分析_Pandas_数据清理、转换、合并、重塑
    利用Python进行数据分析_Pandas_数据加载、存储与文件格式
    利用Python进行数据分析_Pandas_层次化索引
    利用Python进行数据分析_Pandas_处理缺失数据
    利用Python进行数据分析_Pandas_汇总和计算描述统计
    利用Python进行数据分析_Pandas_基本功能
    利用Python进行数据分析_Pandas_数据结构
    fizzbuzz Python很有意思的解法
    javascript Array操作
  • 原文地址:https://www.cnblogs.com/casun547/p/11201102.html
Copyright © 2020-2023  润新知