• bzoj 4556: [Tjoi2016&Heoi2016]字符串


          二分ans,二分区间长度,st表查,最后主席树判断。

          这题最大收获学到了一个nb的卡常技巧,主席树元素个数为0直接返回,不敢相信快了一倍。

        

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define N 200005
      6 using namespace std;
      7 inline int read()
      8 {
      9     int p=0;char c=getchar();
     10     while(c<'0'||c>'9')c=getchar();
     11     while(c>='0'&&c<='9')p=p*10+c-'0',c=getchar();
     12     return p;
     13 }
     14 int wb[N],rank[N],sa[N],sum[N];
     15 int mnn(int x,int y)
     16 {
     17     if(x<y)return x;return y;
     18 }
     19 char s[N];
     20 void da(int n,int m)
     21 {
     22     int *x=rank,*y=wb;
     23     for(int i=0;i<m;i++)sum[i]=0;
     24     for(int i=0;i<n;i++)sum[x[i]=s[i]]++;
     25     for(int i=1;i<m;i++)sum[i]+=sum[i-1];
     26     for(int i=n-1;i>=0;i--)sa[--sum[x[i]]]=i;
     27     int p=1;
     28     for(int j=1;p<n;j<<=1,m=p)
     29     {
     30         p=0;
     31         for(int i=n-j;i<n;i++)y[p++]=i;
     32         for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
     33         for(int i=0;i<m;i++)sum[i]=0;
     34         for(int i=0;i<n;i++)sum[x[i]]++;
     35         for(int i=1;i<m;i++)sum[i]+=sum[i-1];
     36         for(int i=n-1;i>=0;i--)sa[--sum[x[y[i]]]]=y[i];
     37         swap(x,y);x[sa[0]]=0;p=1;
     38         for(int i=1;i<n;i++)
     39          x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
     40     }
     41     return ;
     42 }
     43 int h[N];
     44 void cal(int n)
     45 {
     46     int k=0;
     47     for(int i=1;i<=n;i++)rank[sa[i]]=i;
     48     for(int i=0;i<n;i++)
     49     {
     50         if(k)k--;
     51         int j=sa[rank[i]-1];
     52         while(s[j+k]==s[i+k])k++;
     53         h[rank[i]]=k;
     54     }
     55 }
     56 int n,m;
     57 int mn[N][20];
     58 int lg[N];
     59 int root[N];
     60 void st()
     61 {
     62     int now=0;
     63     for(int i=1;i<=n;i<<=1)
     64     {
     65         for(int j=i;j<i<<1;j++)
     66         {
     67             lg[j]=now;
     68         }
     69         now++;
     70     }
     71     for(int i=1;i<=n;i++)mn[i][0]=h[i];
     72     for(int i=1;i<=18;i++)
     73     {
     74         int k=(1<<(i-1));
     75         for(int j=1;j<=n;j++)
     76         {
     77             if(j+k<=n)mn[j][i]=mnn(mn[j][i-1],mn[j+k][i-1]);
     78             else mn[j][i]=mn[j][i-1];
     79         }
     80     }return ;
     81 }
     82 struct node
     83 {
     84     int l,r,sum;
     85 }a[N*20];int cnt;
     86 void merge(int x,int y,int l,int r,int pos)
     87 {
     88     if(l==r)
     89     {
     90         a[x].sum=1;
     91         return ;
     92     }
     93     int mid=(l+r)>>1;
     94     if(pos<=mid)
     95     {
     96         a[x].l=++cnt;
     97         a[x].r=a[y].r;
     98         merge(a[x].l,a[y].l,l,mid,pos);
     99     }
    100     else
    101     {
    102         a[x].r=++cnt;
    103         a[x].l=a[y].l;
    104         merge(a[x].r,a[y].r,mid+1,r,pos);
    105     }
    106     a[x].sum=a[a[x].l].sum+a[a[x].r].sum;
    107 }
    108 bool qur(int x,int y,int l,int r,int ll,int rr)
    109 {
    110     if(a[x].sum==a[y].sum)return 0;
    111     if(l>=ll&&r<=rr)return a[x].sum!=a[y].sum;
    112     int mid=(l+r)>>1;
    113     if(ll<=mid)if(qur(a[x].l,a[y].l,l,mid,ll,rr))return 1;
    114     if(rr>mid)if(qur(a[x].r,a[y].r,mid+1,r,ll,rr))return 1;
    115     return 0;
    116 }
    117 int t1,t2,t3,t4;
    118 inline int qr(int l,int r)
    119 {
    120     if(l>r)return N;
    121     int k=lg[r-l+1];
    122     return mnn(mn[l][k],mn[r-(1<<k)+1][k]);
    123 }
    124 bool pan(int x)
    125 {
    126      int pos=rank[t3-1];
    127      int ll,rr;
    128      int l=pos,r=n,mid;
    129      while(l<=r)
    130      {
    131          mid=(l+r)>>1;
    132          if(qr(pos+1,mid)<x)r=mid-1;
    133          else l=mid+1;
    134      }
    135      rr=r;
    136      l=1,r=pos;
    137      while(l<=r)
    138      {
    139          mid=(l+r)>>1;
    140          if(qr(mid+1,pos)<x)l=mid+1;
    141          else r=mid-1;
    142      }
    143      ll=l;
    144      return qur(root[rr],root[ll-1],1,n,t1,t2-x+1);
    145 }
    146 
    147 int main()
    148 {
    149     scanf("%d%d",&n,&m);
    150     scanf("%s",s);
    151     da(n+1,256);cal(n);
    152     st();
    153     for(int i=1;i<=n;i++)
    154     {
    155         root[i]=++cnt;
    156         merge(root[i],root[i-1],1,n,sa[i]+1);
    157     }
    158     for(int i=1;i<=m;i++)
    159     {
    160         t1=read();t2=read();t3=read();t4=read();
    161         int l=0;int r=min(t2-t1+1,t4-t3+1);
    162         while(l<=r)
    163         {
    164             int mid=(l+r)>>1;
    165             if(pan(mid))l=mid+1;
    166             else r=mid-1;
    167         }
    168         printf("%d
    ",r);
    169     }
    170     return 0;
    171 }
    172 /*
    173 5 2
    174 ababaa
    175 1 4 2 5
    176 1 4 2 3
    177 */
  • 相关阅读:
    poj 1392 Ouroboros Snake
    poj 1780 Code
    poj 2513 Colored Sticks
    ZOJ 1455 Schedule Problem(差分约束系统)
    poj 3169 Layout (差分约束)
    ZOJ1260/POJ1364国王(King)
    poj 1201/zoj 1508 intervals 差分约束系统
    zoj 2770 Burn the Linked Camp (差分约束系统)
    构造函数和析构函数
    PHP面向对象——静态属性和静态方法
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6279658.html
Copyright © 2020-2023  润新知