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;}

查看7道真题和解析