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\n",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 }