• luogu2336 喵星球上的点名 (SA+二分答案+树状数组)


    离散化一下然后把姓名串和询问串都放一起做SA

    bzoj3277串类似地,满足某一询问的后缀(就是和这个询问对应的后缀的LCP>=这个询问长度的后缀)的排名也是一个区间,把这个区间二分出来即可

    现在要做的两个问题就变成了:

    给定一些区间、一些点,每个点有对应的颜色(就是sa[i]对应的那个姓名串对应的人),问

    1.每个区间中不同颜色的数量:同HH的项链

    2.每个颜色被不同区间覆盖的数量:

      想法其实和1是类似的,扫到区间左端点的时候给a[i]++,扫到右端点的时候给a[对应左端点]--,然后每个点贡献的区间数就是pre[i]-pre[i的颜色上次出现位置],因为相当于我们每次算的是左端点在上次出现位置与现在位置之间的、右端点在现在位置之后的区间,是不重不漏的

    (千万不要写出s[++j]=data[j]=rd();这种代码然后因为某些特性在某些地方A某些地方wa然后跑到讨论区去丢人)

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define ll long long
      4 using namespace std;
      5 const int maxn=4e5+10,maxm=5e4+10,maxq=1e5+10;
      6 
      7 inline ll rd(){
      8     ll x=0;char c=getchar();int neg=1;
      9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     11     return x*neg;
     12 }
     13 
     14 struct Node{
     15     int l,r,i;
     16 }que[maxq];
     17 int NN,N,M,Q;
     18 int data[maxn],s[maxn],bel[maxn];
     19 int sa[maxn],rank[maxn],hei[maxn],rank1[maxn],tmp[maxn],cnt[maxn];
     20 int st[maxn][20],pos[maxq][2];
     21 int tr[maxn],L[maxn],lst[maxn],ans[maxq];
     22 
     23 inline int lowbit(int x){return x&(-x);}
     24 inline void add(int x,int y){
     25     for(;x<=N;x+=lowbit(x)) tr[x]+=y;
     26 }
     27 inline int query(int x){
     28     int re=0;for(;x>0;x-=lowbit(x)) re+=tr[x];return re;
     29 }
     30 
     31 inline void getsa(){
     32     int i,j=0,k;
     33     for(i=1;i<=N;i++) cnt[s[i]]=1;
     34     for(i=1;i<=M;i++) cnt[i]+=cnt[i-1];
     35     for(i=N;i;i--) rank[i]=cnt[s[i]];
     36     
     37     for(k=1;j!=N;k<<=1){
     38         memset(cnt,0,sizeof(cnt));
     39         for(i=1;i<=N;i++) cnt[rank[i+k>N?0:i+k]]++;
     40         for(i=1;i<=M;i++) cnt[i]+=cnt[i-1];
     41         for(i=N;i;i--) tmp[cnt[rank[i+k>N?0:i+k]]--]=i;
     42         memset(cnt,0,sizeof(cnt));
     43         for(i=1;i<=N;i++) cnt[rank[i]]++;
     44         for(i=1;i<=M;i++) cnt[i]+=cnt[i-1];
     45         for(i=N;i;i--) sa[cnt[rank[tmp[i]]]--]=tmp[i];
     46         memcpy(rank1,rank,sizeof(rank1));
     47         rank[sa[1]]=j=1;
     48         for(i=2;i<=N;i++){
     49             if(rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+k>N?0:sa[i]+k]!=rank1[sa[i-1]+k>N?0:sa[i-1]+k]) j++;
     50             rank[sa[i]]=j;
     51         }M=j;
     52     }
     53     for(i=1;i<=N;i++) sa[rank[i]]=i;
     54 }
     55 
     56 inline void geth(){
     57     for(int i=1,j=0;i<=N;i++){
     58         if(rank[i]==1) continue;
     59         if(j) j--;
     60         int x=sa[rank[i]-1];
     61         while(x+j<=N&&i+j<=N&&s[x+j]==s[i+j]) j++;
     62         hei[rank[i]]=j;
     63     }
     64 }
     65 
     66 inline void getst(){
     67     for(int i=N;i;i--){
     68         st[i][0]=hei[i];
     69         for(int j=1;st[i+(1<<(j-1))][j-1];j++){
     70             st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
     71         }
     72     }
     73 }
     74 
     75 inline int rmq(int l,int r){
     76     int x=log2(r-l+1);
     77     return min(st[l][x],st[r-(1<<x)+1][x]);
     78 }
     79 
     80 inline void getq(int id,int p,int x){
     81     int l0,r0,l,r;
     82     if(hei[p+1]<x) r0=p;
     83     else{
     84         l=p+1,r=N;
     85         while(l<=r){
     86             int m=l+r>>1;
     87             if(rmq(p+1,m)>=x) r0=m,l=m+1;
     88             else r=m-1;
     89         }
     90     }
     91     if(hei[p]<x) l0=p;
     92     else{
     93         l=2,r=p;
     94         while(l<=r){
     95             int m=l+r>>1;
     96             if(rmq(m,p)>=x) l0=m-1,r=m-1;
     97             else l=m+1;
     98         }
     99     }
    100     que[id].l=l0,que[id].r=r0,que[id].i=id;
    101 }
    102 
    103 inline bool cmp(Node a,Node b){
    104     return a.r<b.r;
    105 }
    106 
    107 inline void solve(){
    108     int i,j,k;
    109     for(i=1;i<=Q;i++){
    110         getq(i,rank[pos[i][0]],pos[i][1]-pos[i][0]+1);
    111         L[i]=que[i].l;
    112     }sort(que+1,que+Q+1,cmp);
    113     sort(L+1,L+Q+1);
    114     
    115     for(i=1,j=1;i<=N&&j<=Q;i++){
    116         int x=bel[sa[i]];
    117         if(x){
    118             if(lst[x]) add(lst[x],-1);
    119             add(i,1);lst[x]=i;
    120         }
    121         for(;que[j].r==i&&j<=Q;j++){
    122             ans[que[j].i]=query(que[j].r)-query(que[j].l-1);
    123         }
    124     }
    125     for(i=1;i<=Q;i++) printf("%d
    ",ans[i]);
    126     memset(ans,0,sizeof(ans));
    127     memset(lst,0,sizeof(lst));
    128     memset(tr,0,sizeof(tr));
    129     for(i=1,j=1,k=1;i<=N;i++){
    130         for(;j<=Q&&L[j]==i;j++) add(i,1);
    131         ans[bel[sa[i]]]+=query(i)-query(lst[bel[sa[i]]]);
    132         lst[bel[sa[i]]]=i;
    133         for(;k<=Q&&que[k].r==i;k++) add(que[k].l,-1);
    134     }for(i=1;i<=NN;i++) printf("%d ",ans[i]);
    135 }
    136 
    137 int main(){
    138     //freopen("2336.in","r",stdin);
    139     int i,j,k;
    140     NN=N=rd(),Q=rd();
    141     for(i=1,j=0;i<=N*2+Q;i++){
    142         int a=rd();
    143         if(i>N*2) pos[i-N*2][0]=j+1,pos[i-N*2][1]=j+a;
    144         for(k=0;k<a;k++){
    145             s[j]=data[++j]=rd();
    146             if(i<=N*2) bel[j]=(i+1)/2;
    147         }
    148         s[j]=data[++j]=-1;
    149     }N=j;
    150     sort(data+1,data+N+1);
    151     M=unique(data+1,data+N+1)-data-1;
    152     for(i=1;i<=N;i++) s[i]=lower_bound(data+1,data+M+1,s[i])-data-1;
    153     M+=5;
    154     getsa();geth();getst();
    155     solve();
    156     return 0;
    157 }
  • 相关阅读:
    Springboot中使用Scala开发
    aliyun阿里云Maven仓库地址
    css文字滚动
    随笔
    下拉菜单事件
    微信分享
    微信分享功能
    随笔记
    全屏设置
    判定复选框的选中状态
  • 原文地址:https://www.cnblogs.com/Ressed/p/9681856.html
Copyright © 2020-2023  润新知