zoukankan      html  css  js  c++  java
  • [gym102769L]Lost Temple

    考虑第$i$列的答案,即找到一个区间$[l,r]$,使得:

    1.$l$和$r$要同奇偶,令$ans=frac{r-l}{2}$,要求尽量大($ans+1$即为该列答案)

    2.$forall 0le jle ans$,$[l+j,r-j]subseteq [l_{i-j},r_{i-j}],[l_{i+j},r_{i+j}]$(两个都包含)

    两个都包含可以看成求交,那么即$lge max(l_{i-j},l_{i+j})-j$,类似的$rle min(r_{i-j},r_{i+j})+j$,很明显$l$和$r$都会取到端点,只需要保证长度足够,即$ans$合法当且仅当
    $$
    min_{0le jle ans}(min(r_{i-j},r_{i+j})+j)-max_{0le jle ans}(max(l_{i-j},l_{i+j})-j)ge 2ans
    $$
    由于相邻两列答案至多相差1,记上一列的答案为$ans$,那么只需要判定$anspm 1$即可

    注意到一次判定也就是求区间$l_{i}/r_{i}pm i$最小和最大值,用树状数组维护复杂度过高,考虑用单调队列来维护,通过调整判定$anspm 1$的顺序每一次询问的右端点单调不下降,左端点至多减小1,复杂度为$o(n)$

    时间复杂度为$o(n)$,且常数略大

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 5000005 
     4 #define mod 998244353
     5 #define ull unsigned long long
     6 int t,n,ans,sum,mi[N],l[N],r[N];
     7 struct pqueue{
     8     int p,L,R,x,y,a[N],q[N];
     9     void add(int k){
    10         while ((x<y)&&(a[k]<=a[q[y-1]]))y--;
    11         q[y++]=k;
    12     }
    13     int query(int l,int r){
    14         int ans=0x3f3f3f3f;
    15         //q头尾为[x,y],是[L,R]的单调队列,询问[l,r] 
    16         for(int i=l;i<L;i++)ans=min(ans,a[i]);
    17         assert(R<=r);
    18         while (R<r)add(++R);
    19         if (L<l){
    20             L=l;
    21             while ((x<y)&&(q[x]<L))x++;
    22         }
    23         ans=min(ans,a[q[x]]);
    24         return p*ans;
    25     }
    26 }Q[4];
    27 ull calc(ull &A,ull &B){
    28     ull T=A,S=B;
    29     A=S;
    30     T^=(T<<23);
    31     T^=(T>>17);
    32     T^=(S^(S>>26));
    33     B=T;
    34     return T+S;
    35 }
    36 void read(){
    37     int L,X,Y;
    38     ull A,B; 
    39     scanf("%d%d%d%llu%llu",&L,&X,&Y,&A,&B);
    40     for(int i=1;i<=n;i++){
    41         l[i]=calc(A,B)%L+X;
    42         r[i]=calc(A,B)%L+Y;
    43         if (l[i]>r[i])swap(l[i],r[i]);
    44     }
    45 }
    46 void init(){
    47     for(int i=0;i<4;i++)Q[i].L=Q[i].R=Q[i].x=Q[i].y=0;
    48     for(int i=1;i<=n;i++)Q[0].a[i]=r[i]-i;
    49     for(int i=1;i<=n;i++)Q[1].a[i]=r[i]+i;
    50     for(int i=1;i<=n;i++)Q[2].a[i]=-(l[i]+i);
    51     for(int i=1;i<=n;i++)Q[3].a[i]=-(l[i]-i);
    52 }
    53 bool check(int i,int ans){
    54     if ((i+ans>n)||(i-ans<=0))return 0;
    55     int r=min(Q[0].query(i-ans,i)+i,Q[1].query(i,i+ans)-i);
    56     int l=max(Q[2].query(i-ans,i)-i,Q[3].query(i,i+ans)+i);
    57     return r-l>=2*ans;
    58 }
    59 int main(){
    60     mi[0]=1;
    61     for(int i=1;i<N-4;i++)mi[i]=3LL*mi[i-1]%mod;
    62     Q[0].p=Q[1].p=1;
    63     Q[2].p=Q[3].p=-1;
    64     scanf("%d",&t);
    65     for(int ii=1;ii<=t;ii++){
    66         scanf("%d",&n);
    67         read();
    68         init();
    69         ans=0;
    70         sum=1;
    71         for(int i=2;i<=n;i++){
    72             if (!check(i,ans))ans--;
    73             else{
    74                 if (check(i,ans+1))ans++;
    75             }
    76             sum=(sum+1LL*mi[i-1]*(ans+1))%mod;
    77         }
    78         printf("Case #%d: %d
    ",ii,sum);
    79     }
    80 }
    View Code
  • 相关阅读:
    关于2021-01-13爆发的incaseformat病毒相关信息收集1.2(持续更新和关注中...)
    (转)服务器UDIMM、LRDIMM、RDIMM三种内存的区别
    Shred命令 学习
    关于图片文件的元数据信息清理和时间戳修改
    关于Chrome 浏览器 “小尾巴”问题的解决办法
    CF471D MUH and Cube Walls -kmp
    UVA12467 Secret Word -kmp
    UVA12604 Caesar Cipher -kmp
    【JLOI2007】周期串
    Http协议
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14367715.html
Copyright © 2011-2022 走看看