[ 莫队 ] [ YNOI2017 ] BZOJ4866

来源:互联网 发布:mac ssh alias 编辑:程序博客网 时间:2024/06/06 04:33

能形成回文串的条件是出现奇数次的字母至多有一个。
然后记一下每种状态出现次数,莫队就好了。
卡了2个小时常数,最后加了个优化才过。。

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=x*10+c-48,c=nc());}typedef long long ll;typedef unsigned short sh;const int N=60010;int k,n,m,a[N];int L=1,R,p,sum;int h[30],b[N],s;sh cnt[1<<26];int l[N],r[N],cc;ll Ans[N],Res;struct Node{    int l,r,id;    bool operator < (Node x)const{        return b[l]<b[x.l]||(b[l]==b[x.l]&&(b[l]&1?r<x.r:r>x.r));    }}c[N];inline void Add1(int x){    Res+=cnt[x]++;    if(r[L]>R)return(void)(Res+=(L<n));    for(int i=0;i<26;i++)Res+=cnt[x^h[i]];}inline void Add2(int x){    Res+=cnt[x]++;    if(l[R]<L)return(void)(Res+=(R>1));    for(int i=0;i<26;i++)Res+=cnt[x^h[i]];}inline void Del1(int x){    Res-=--cnt[x];    if(r[L]>R)return(void)(Res-=(L<n));    for(int i=0;i<26;i++)Res-=cnt[x^h[i]];}inline void Del2(int x){    Res-=--cnt[x];    if(l[R]<L)return(void)(Res-=(R>1));    for(int i=0;i<26;i++)Res-=cnt[x^h[i]];}int main(){    Read(n);Read(m);    char C=nc();    for(;C<'a'||C>'z';C=nc());    for(int i=1;i<=n;i++)a[i]=C-'a',C=nc();    s=sqrt(n)*2;    for(int i=0;i<n;i++)b[i]=i/s;    h[0]=1;    for(int i=1;i<26;i++)h[i]=h[i-1]<<1;    for(int i=1;i<=m;i++)Read(c[i].l),c[i].l--,Read(c[i].r),c[i].id=i;    sort(c+1,c+m+1);    for(int i=1;i<=n;i++)a[i]=a[i-1]^h[a[i]];    for(int i=0;i<=n;i++){        sh j=0;        for(int k=0;k<26;k++)        j=max(j,cnt[h[k]^a[i]]);        l[i]=j;        cnt[a[i+1]]=i+1;    }    memset(cnt,0,sizeof(cnt));    for(int i=n;i>=0;i--){        sh j=n+1;        for(int k=0;k<26;k++)        if(cnt[h[k]^a[i]])j=min(j,cnt[h[k]^a[i]]);        r[i]=j;        cnt[a[i+1]]=i+1;    }    memset(cnt,0,sizeof(cnt));    for(int i=1;i<=m;i++){        while(L>c[i].l)Add1(a[--L]);        while(R<c[i].r)Add2(a[++R]);        while(L<c[i].l)Del1(a[L]),L++;        while(R>c[i].r)Del2(a[R]),R--;        Ans[c[i].id]=Res;    }    for(int i=1;i<=m;i++)printf("%lld\n",Ans[i]);    return 0;}
原创粉丝点击