zoukankan      html  css  js  c++  java
  • [atARC102F]Revenge of BBuBBBlesort

    定义以$i$为中心(交换$p_{i-1}$和$p_{i+1}$)的操作为操作$i$

    结论1:若执行过操作$i$,则之后任意时刻都无法执行操作$i-1$或操作$i+1$

    当执行操作$i$后,必然有$p_{i-1}<p_{i}$,然后不妨假设下一次与$i$相邻的操作为$i-1$($i+1$类似)

    操作$i-1$的条件为$p_{i-2}>p_{i-1}>p_{i}$,即要增大$p_{i-1}$或减小$p_{i}$,可以执行操作$i-2$或操作$i+1$,后者根据假设不成立

    对于操作$i-2$,其执行完后必然有$p_{i-2}<p_{i-1}$,类似的我们又要求执行操作$i-3$来增大$p_{i-2}$……以此类推,当需要执行操作1来增大$p_{2}$即不合法

    推论1:执行操作$i$必须有$p_{i}=i$

    根据结论1,执行操作$i$后无法再执行操作$i-1$或$i+1$,即无法再修改$p_{i}$,而最终要求$p_{i}=i$

    推论2:若初始$p_{i} e i$,则一定不会执行操作$i$;若$p_{i}=i$,则一定不会执行操作$i-1$或操作$i+1$

    根据推论1,执行操作$i$需要$p_{i}=i$,而修改$p_{i}$必然执行了操作$i-1$或$i+1$,则不能执行操作$i$

    根据推论1,执行操作$i-1$($i+1$类似)要求$p_{i-1}=i-1<p_{i}$,不成立

    考虑将整个序列划分为独立的若干段,即要求每一段的端点都不能操作,这等价于将其在$i$和$i+1$之间断开则要求$i$和$i+1$都无法操作,不妨将所有这些位置都断开,考虑每一段的形式:

    1.那么每一段必然不会出现相邻两数$i$和$i+1$使得$[p_{i}=i]=[p_{i+1}=i+1]$,否则必然可以断开

    2.如果端点满足$p_{i}=i$(以下假设为左端点),则$i$无法操作,同时$i+1$也无法操作,可以断开(除非$i+1$不在该段中,即仅一个$p_{i}=i$)

    更形象的,记$s_{i}=[p_{i}=i]$(一个01串),那么最终每一段的$s$分为两种:1.仅一个'1';2.以'0'为开头结尾的'01010...10'

    对于第1种段直接删去即可,对于第2种继续分析

    可以看作对$p_{l},p_{l+2},...,p_{r}$这一段排序,而要交换$p_{i}$和$p_{i+2}$,则要求$p_{i}>i+1>p_{i+2}$

    由于$p_{i}equiv i(mod 2)$,因此$p_{i}>i+1$也即$p_{i}>i$,类似的后者也即$i+2>p_{i+2}$

    对于初始$p_{i}>i$的位置,其一定只能向后交换,且若交换至$p_{i}=i$,根据推论2,一定不会再改变($p_{i}<i$的位置类似)

    其限制且仅限制(若两点都满足交换方向一定可行)了每一个数的交换方向,那么合法即要求:

    1.如果是区间$[l,r]$,$forall lle ile r,lle p_{i}le r$

    2.对于$p_{i}>i$的位置,其之前不存在比其大的数;对于$p_{i}<i$的位置,其之后不存在比其小的数

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 300005
     4 int n,a[N],p[N];
     5 int main(){
     6     scanf("%d",&n);
     7     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
     8     for(int i=1;i<=n;i++)p[i]=1;
     9     for(int i=1;i<=n;i++)
    10         if (a[i]!=i)p[i]=0;
    11         else p[i-1]=p[i+1]=0;
    12     for(int i=1,j=1;i<=n;i=++j){
    13         for(;j<n;j++)
    14             if ((!p[j])&&(!p[j+1]))break;
    15         if ((i==j)&&(p[i]==i))continue;
    16         for(int k=i;k<=j;k++)
    17             if ((a[k]<i)||(j<a[k])){
    18                 printf("No");
    19                 return 0;
    20             }
    21         int mx=0,mn=n;
    22         for(int k=i;k<=j;k++){
    23             if ((a[k]>k)&&(a[k]<mx)){
    24                 printf("No");
    25                 return 0;
    26             }
    27             mx=max(mx,a[k]);
    28         }
    29         for(int k=j;k>=i;k--){
    30             if ((a[k]<k)&&(a[k]>mn)){
    31                 printf("No");
    32                 return 0;
    33             }
    34             mn=min(mn,a[k]);
    35         }
    36     }
    37     printf("Yes");
    38 }
    View Code
  • 相关阅读:
    Postman使用教程
    CAD和ArcGIS转换 矢量配准
    SAP CRM Advanced search和Simple search里Max hit表现行为的差异
    SAP CRM Product simple search的启用步骤
    如何快速定位SAP CRM订单应用(Order Application)错误消息抛出的准确位置
    如何动态修改SAP CRM WebClient UI表格栏的宽度
    如何在SAP CRM WebClient UI里创建web service并使用ABAP消费
    如何处理SAP CRM Web Service错误
    如何使用SAP CRM WebClient UI实现一个类似新浪微博的字数统计器
    如何开启SAP CRM基于WORD模板创建附件的功能
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13957452.html
Copyright © 2011-2022 走看看