P3604 美好的每一天 莫队 + 思维

传送门

真是个练习卡常的好题呢

题意:给定一个串,让后每次给定一个区间,问这个区间的子区间为回文子区间有多少个。这里的回文串是区间内字母重排之后是回文串即可。
既然重排之后是回文就行,那么只需要知道这个区间内奇数的个数就行了。字母只有26个,那么可以状态压缩一下,用一个数组记录一下每一位即可。
既然只关心个数的奇偶,那么可以用异或来判断。区间异或显然可以转换成前缀异或,假设当前区间为 [ x , y ] ,那么需要选择两个数 i j ∈ [ x - 1 , y ] ,使其异或值为 0 (此时奇数个数为0) 或者2 ^ n (此时为奇数有一个) 即可。而我假设 cnt 为记录的前缀异或和数量的数组,加入当前要加的数为 a [ x ] ,那么可以将 a [ x ] ^ ( 2 ^ n , n ∈ [ 0 , 25 ] ) 得到相应的数,加上其个数即可,让后再加上跟自身相同的数个数 ( 也就是异或结果为0 )。这样就解决了。

我不怎么喜欢卡常好吧是我不会卡常 ,能过了就行了 ~ ~ ~

#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define pb push_back
#define mk make_pair
#define re register
#define il inline
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

const int N=60010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n,m;
int ans[N],cnt[(1<<26)+3],id[N],now,a[N];
char s[N];
struct Node
{
    int l,r;
    int id;
}q[N];

il bool cmp(Node a,Node b)
{
    return id[a.l]^id[b.l]? a.l<b.l : ((id[a.l]&1)? a.r<b.r : a.r>b.r);
}

void del(int x)
{
    cnt[x]--; now-=cnt[x];//把与它异或为0的去掉
    for(re int i=0;i<26;i++)
        now-=cnt[x^(1<<i)];
}

void add(int x)
{
    now+=cnt[x]; cnt[x]++;//先把异或为0的加上
    for(re int i=0;i<26;i++)
        now+=cnt[x^(1<<i)];
}

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    scanf("%d%d",&n,&m);  cin>>s+1;
    int se=sqrt(n);
    for(re int i=1;i<=n;i++)
    {
        int x=s[i]-'a';
        a[i]=1<<x; a[i]^=a[i-1];
        id[i]=(i-1)/se+1;
    }
    for(re int i=1;i<=m;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
    sort(q+1,q+1+m,cmp);
    int l=1,r=0;
    for(re int i=1;i<=m;i++)
    {
        int lx=q[i].l-1,rx=q[i].r;
        while(l<lx) del(a[l++]);
        while(l>lx) add(a[--l]);
        while(r<rx) add(a[++r]);
        while(r>rx) del(a[r--]);
        ans[q[i].id]=now;
    }
    for(re int i=1;i<=m;i++) printf("%d\n",ans[i]);



	return 0;
}
/*

*/



猜你喜欢

转载自blog.csdn.net/DaNIelLAk/article/details/108382016