2021“MINIEYE杯”中国大学生算法设计超级联赛(10)Pty loves string(Border+二维数点)
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                2021“MINIEYE杯”中国大学生算法设计超级联赛(10)Pty loves string(Border+二维数点)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.                        
                                Pty loves string
建立Border樹后,發(fā)現(xiàn)可以轉(zhuǎn)化成兩個子樹中相同點的數(shù)量,時間戳轉(zhuǎn)化為連續(xù)的區(qū)間后相當(dāng)于有兩個數(shù)組,每次給兩個區(qū)間,問區(qū)間相同點權(quán)的數(shù)目。
第一個數(shù)組作為區(qū)間,第二個數(shù)組作為權(quán)值。將第一個數(shù)組建立主席樹,每次插入的是第一個區(qū)間位置的權(quán)值映射到第二個數(shù)組中的權(quán)值。然后就是區(qū)間查詢。
#include<bits/stdc++.h>using namespace std; const int N=200010; char s[N]; int n,m; int ne1[N],ne2[N]; vector<int> e1[N],e2[N]; int dfn1[N],dfn2[N],sz1[N],sz2[N],timestamp; int id[N]; struct node {int l,r,v; }tree[N*40]; int rt[N],cnt; void insert(int &u,int o,int l,int r,int v) {tree[u=++cnt]=tree[o];tree[u].v++;if(l==r) return;int mid=l+r>>1;if(v<=mid)insert(tree[u].l,tree[o].l,l,mid,v);elseinsert(tree[u].r,tree[o].r,mid+1,r,v); } int query(int u,int o,int l,int r,int L,int R) {if(L<=l&&r<=R) return tree[u].v-tree[o].v;int v=0;int mid=l+r>>1;if(L<=mid) v+=query(tree[u].l,tree[o].l,l,mid,L,R);if(R> mid) v+=query(tree[u].r,tree[o].r,mid+1,r,L,R);return v; } void dfs1(int u) {sz1[u]=1;dfn1[u]=++timestamp;id[timestamp]=u;for(int v:e1[u]){dfs1(v);sz1[u]+=sz1[v];} } void dfs2(int u) {sz2[u]=1;dfn2[u]=++timestamp;for(int v:e2[u]){dfs2(v);sz2[u]+=sz2[v];} } void init() {for(int i=1;i<=cnt;i++) tree[i]={0,0,0};cnt=0;for(int i=0;i<=n+1;i++) e1[i].clear(),e2[i].clear();ne1[1]=0;for(int i=2,j=0;i<=n;i++){while(j&&s[i]!=s[j+1]) j=ne1[j];if(s[i]==s[j+1]) j++;ne1[i]=j;}ne2[n]=n+1;for(int i=n-1,j=n+1;i;i--){while(j<=n&&s[i]!=s[j-1]) j=ne2[j];if(s[i]==s[j-1]) j--;ne2[i]=j;} } void build() {for(int i=1;i<=n;i++) e1[ne1[i]].push_back(i),e2[ne2[i]].push_back(i);timestamp=0;dfs1(0);timestamp=0;dfs2(n+1);for(int i=1;i<=n+1;i++) insert(rt[i],rt[i-1],1,n+1,dfn2[id[i]+1]); } int main() {int Tc;scanf("%d",&Tc);while(Tc--){scanf("%d%d%s",&n,&m,s+1);init();build();while(m--){int x,y;scanf("%d%d",&x,&y);if(x+y>n) {puts("0");continue;}y=n-y+1;printf("%d\n",query(rt[dfn1[x]+sz1[x]-1],rt[dfn1[x]-1],1,n+1,dfn2[y],dfn2[y]+sz2[y]-1));}}return 0; }總結(jié)
以上是生活随笔為你收集整理的2021“MINIEYE杯”中国大学生算法设计超级联赛(10)Pty loves string(Border+二维数点)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 1589 元含税包邮:哈曼卡顿琉璃 4
- 下一篇: [BZOJ5312]冒险(势能线段树)
