P3604 美好的每一天

P3604 美好的每一天

链接

P3604 美好的每一天

题解

这题思路挺明显的,但是真的卡的我好难受。
能重排形成回文串的区间内出现奇数次的字母不能超过一个,又是lxl出的题,做法就很显然了。
但是还是不停地MLE和TLE,看了题解发现储存 (2^{26}) 种状态的数组可以用unsigned short (0~65535) 。。。。
然后开着O2勉强过了。

(Code)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=6e4+10;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char get(){
	char ch=getchar();
	while(ch<'a'||ch>'z') ch=getchar();
	return ch;
}
void print(LL x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int E;
int n,m;
int s[N];
unsigned char g[N];
LL ans[N];
struct query{
	int l,r,id;
}q[N];
unsigned short c[(1<<26)+10];
bool cmp(query x,query y){
	if(g[x.l]!=g[y.l]) return g[x.l]<g[y.l];
	return x.r<y.r;
}
LL now;
inline void add(int x,LL f){
	LL re=0;
	if(f<0) --c[x];
	re=c[x];
	for(register int i=0;i<26;++i) re+=c[x^(1<<i)];
	if(f>0) ++c[x];
	now+=f>0?re:-re;
}
int main(){
	char ch;
	scanf("%d%d",&n,&m);E=sqrt(n)*2;
	for(register int i=1;i<=n;++i){
		ch=get();
		s[i]=s[i-1]^(1<<(ch-'a'));
		g[i]=(i+E-1)/E;
	}
	for(register int i=1;i<=m;++i) {
		q[i].l=read();q[i].r=read();
		q[i].id=i;
	}
	sort(q+1,q+1+m,cmp);
	int l=1,r=0;++c[s[0]];now=0;
	for(register int i=1;i<=m;++i){
		while(l>q[i].l){add(s[l-2],1LL);--l;}
		while(r<q[i].r){add(s[r+1],1LL);++r;}
		while(l<q[i].l){add(s[l-1],-1LL);++l;}
		while(r>q[i].r){add(s[r],-1LL);--r;}
		ans[q[i].id]=now;
	}
	for(register int i=1;i<=m;++i) {
		print(ans[i]);
		puts("");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Yuigahama/p/13504362.html