6
重排的回文串
http://www.nowcoder.com/questionTerminal/a45ace35d2414b4081b229100d96d7aa
include
include
include
include
include
using namespace std;
typedef long long ll;
const int A = 1e5 + 10;
vector<int> v;
int siz,sum[A],n,m;
ll Ans[A],cnt[A],res;
char s[A];
class Que{
public:
int l,r,id;
bool operator<(const Que& rhs) const{
if(l/siz == rhs.l/siz) return r/siz < rhs.r/siz;
return l/siz < rhs.l/siz;
}
}Q[A];
class Gra{
public:
int v,next;
}G[A*50];
int head[A],tot;</int>
void update(int pos,int c){
if(c == -1) cnt[sum[pos]] += c;
res += ccnt[sum[pos]];
for(int i=head[sum[pos]] ;i!=-1 ;i=G[i].next){
res += ccnt[G[i].v];
}
if(c == 1) cnt[sum[pos]] += c;
}
void add(int u,int v){
G[tot].v = v;
G[tot].next = head[u];
head[u] = tot++;
}
void solve(){
int L = 0,R = -1;res = 0;
for(int i=1 ;i<=m ;i++){
int id = Q[i].id;
while(R < Q[i].r) update(++R,1);
while(L > Q[i].l) update(--L,1);
while(R > Q[i].r) update(R--,-1);
while(L < Q[i].l) update(L++,-1);
Ans[id] = res;
}
}
int main(){
scanf("%d%d",&n,&m);
scanf("%s",s+1);
sum[0] = 0;v.push_back(0); siz = sqrt(1.0*n); for(int i=1 ;i<=n ;i++){ sum[i] = sum[i-1]^(1<<(s[i]-'a')); v.push_back(sum[i]); } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); int len = v.size(); memset(head,-1,sizeof(head));tot = 0; for(int i=0 ;i<len ;i++){ for(int j=0 ;j<26 ;j++){ int x = v[i]^(1<<j); int k = lower_bound(v.begin(),v.end(),x) - v.begin(); if(k>=0 && k<v.size() && v[k] == x) add(i,k); } } for(int i=0 ;i<=n ;i++) sum[i] = lower_bound(v.begin(),v.end(),sum[i]) - v.begin(); for(int i=1 ;i<=m ;i++){ scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id = i;Q[i].l--; } sort(Q+1,Q+1+m); solve(); for(int i=1 ;i<=m ;i++){ printf("%lld\n",Ans[i]); } return 0;
}