• 洛谷P3604 美好的每一天(莫队)


    传送门

    由乃的题还是一如既往的可怕……

    先放上原题解

    标解:

    一个区间可以重排成为回文串,即区间中最多有一个字母出现奇数次,其他的都出现偶数次

    发现这个和  类似

    
    
    
    
    

    这样如果一个区间的  和为  或者  ,则这个区间可以重排成为回文串,即回归天空

    把每个位置的值变为前缀  和,那么区间  可以回归天空当且仅当  为  或者 

     即  的异或和

    这样用莫队算法,可以做到  的复杂度

    然后怎么用莫队?可以参考一下这道题目->异或序列

    考虑区间$[l,r]->[l,r+1]$就是要看这个区间里有多少前缀异或$a[r+1]$等于$0$或$1<<x$

    那么只要用桶存起来就好了

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 inline int read(){
     8     #define num ch-'0'
     9     char ch;bool flag=0;int res;
    10     while(!isdigit(ch=getchar()))
    11     (ch=='-')&&(flag=true);
    12     for(res=num;isdigit(ch=getchar());res=res*10+num);
    13     (flag)&&(res=-res);
    14     #undef num
    15     return res;
    16 }
    17 char sr[1<<21],z[20];int C=-1,Z;
    18 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    19 inline void print(int x){
    20     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    21     while(z[++Z]=x%10+48,x/=10);
    22     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    23 }
    24 const int N=60005,M=(1<<26)+5;
    25 int a[N],rt[N],l,r,n,m,bl;char s[N];
    26 struct node{
    27     int l,r,id;
    28     inline bool operator <(const node b)const
    29     {
    30         if(rt[l]!=rt[b.l]) return l<b.l;
    31         return rt[l]&1?r<b.r:r>b.r;
    32     }
    33 }q[N];
    34 unsigned short c[M];
    35 int ans[N],ansn;
    36 inline void add(int x){
    37     ansn+=c[a[x]];
    38     for(int i=0;i<26;++i) ansn+=c[a[x]^(1<<i)];
    39     ++c[a[x]];
    40 }
    41 inline void del(int x){
    42     --c[a[x]];
    43     ansn-=c[a[x]];
    44     for(int i=0;i<26;++i) ansn-=c[a[x]^(1<<i)];
    45 }
    46 int main(){
    47     n=read(),m=read(),bl=sqrt(n);
    48     scanf("%s",s+1);
    49     for(int i=1;i<=n;++i) a[i]=(1<<(s[i]-'a'))^a[i-1],rt[i]=(i-1)/bl+1;
    50     for(int i=1;i<=m;++i) 
    51     q[i].l=read()-1,q[i].r=read(),q[i].id=i;
    52     sort(q+1,q+1+m);
    53     l=0,r=0,c[0]=1;
    54     for(int i=1;i<=m;++i){
    55         while(l>q[i].l) add(--l);
    56         while(r<q[i].r) add(++r);
    57         while(l<q[i].l) del(l++);
    58         while(r>q[i].r) del(r--);
    59         ans[q[i].id]=ansn;
    60     }
    61     for(int i=1;i<=m;++i) print(ans[i]);
    62     Ot();
    63     return 0;
    64 }

     然而实际上每一次都要做位运算太慢了,可以直接一波离散把所有能转移到的状态找出来,然后就会快很多(上面那个 7040ms,下面这个938ms)

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 inline int read(){
     8     #define num ch-'0'
     9     char ch;bool flag=0;int res;
    10     while(!isdigit(ch=getchar()))
    11     (ch=='-')&&(flag=true);
    12     for(res=num;isdigit(ch=getchar());res=res*10+num);
    13     (flag)&&(res=-res);
    14     #undef num
    15     return res;
    16 }
    17 char sr[1<<21],z[20];int C=-1,Z;
    18 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    19 inline void print(int x){
    20     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    21     while(z[++Z]=x%10+48,x/=10);
    22     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    23 }
    24 const int N=60005,M=(1<<26)+5;
    25 int a[N],b[N],rt[N],l,r,n,m,bl,ver[N*30],Next[N*30],head[N],tot;char s[N];
    26 struct node{
    27     int l,r,id;
    28     inline bool operator <(const node b)const
    29     {
    30         if(rt[l]!=rt[b.l]) return l<b.l;
    31         return rt[l]&1?r<b.r:r>b.r;
    32     }
    33 }q[N];
    34 unsigned short c[M];
    35 int ans[N],ansn;
    36 inline void addedge(int u,int v){
    37     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
    38 }
    39 inline void add(int x){
    40     for(int i=head[a[x]];i;i=Next[i]) ansn+=c[ver[i]];
    41     ++c[a[x]];
    42 }
    43 inline void del(int x){
    44     --c[a[x]];
    45     for(int i=head[a[x]];i;i=Next[i]) ansn-=c[ver[i]];
    46 }
    47 int main(){
    48     //freopen("testdata.in","r",stdin);
    49     n=read(),m=read(),bl=sqrt(n);
    50     scanf("%s",s+1);
    51     for(int i=1;i<=n;++i) b[i]=a[i]=(1<<(s[i]-'a'))^a[i-1],rt[i]=i/bl;
    52     sort(b,b+1+n);
    53     int k=unique(b,b+1+n)-b;
    54     for(int i=0;i<k;++i){
    55         for(int j=0;j<26;++j){
    56             int t=b[i]^(1<<j);
    57             int y=lower_bound(b,b+k,t)-b;
    58             if(b[y]==t) addedge(i,y);
    59         }
    60         addedge(i,i);
    61     }
    62     for(int i=1;i<=n;++i) a[i]=lower_bound(b,b+k,a[i])-b;
    63     for(int i=1;i<=m;++i) 
    64     q[i].l=read()-1,q[i].r=read(),q[i].id=i;
    65     sort(q+1,q+1+m);
    66     l=0,r=0,c[0]=1;
    67     for(int i=1;i<=m;++i){
    68         while(l>q[i].l) add(--l);
    69         while(r<q[i].r) add(++r);
    70         while(l<q[i].l) del(l++);
    71         while(r>q[i].r) del(r--);
    72         ans[q[i].id]=ansn;
    73     }
    74     for(int i=1;i<=m;++i) print(ans[i]);
    75     Ot();
    76     return 0;
    77 }
  • 相关阅读:
    Webpack笔记(三)——一款破产版脚手架的开发
    Google C++命名规范
    视觉词袋模型(BOVW)
    机器学习之四:决策树
    Zernike不变矩
    互联网产品各阶段的标准流程文档
    机器学习之三:logistic回归(最优化)
    Python
    机器学习之二:K-近邻(KNN)算法
    Python学习之二:Python 与 C 区别
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9538436.html
Copyright © 2020-2023  润新知