PERPALIN 可以考虑最后的状态可以是两个非常长而且相同的前缀和后缀中间再加一小段,然后就是不断缩小区间至出解
CHEFHPAL 发现当字符集大于等于3的时候abc循环一定是没有大于1的回文子串的,现在考虑字符集为2的情况,我是打表发现的,1-8可以暴力做,大于等于9的部分答案都可以做到4,只要abaabb循环就好了
CSUBQ 答案其实就是没有大于R的区间个数-没有大于等于L的区间个数,可以建两个线段树分别维护,询问就是全1的区间个数,就可以做了
SEGPROD 其实这是个小技巧,我在knowledge
里有写
我贴贴代码在下面:
PERPALIN:
const int N=1e5+11;
char s[N];
int n;
int solve(int n,int p) {
while(n > 3 && p != 1 && n != p) {
if(n<p) {
if(p%n) return -1;
else n=p;
}
if(n%p) return -1;
int t=(n&1);
n/=2,n%=p,n=2*n+t;
}
if(p<3 || (n&&n<3) || n%p) return -1;
if(p%2) {
rep(i,1,p/2)s[i]='a';
s[p/2+1]='b';
rep(i,p/2+2,p)s[i]='a';
} else {
rep(i,1,p/2) s[i]='a';
s[p/2]=s[p/2+1]='b';
rep(i,p/2+2,p)s[i]='a';
}
s[p+1]=0;
return p;
}
int main(){
int T=rd();
while(T--){
int n=rd(),p=rd();
int t=solve(n,p);
if(t==1 || t==-1) puts("impossible");
else {
rep(i,1,n/t) printf("%s",s+1);
putchar('\n');
}
}
}
CHEFHPAL:
const char s[]="abcdefghijklmnopqrstuvwxyz233333";
const char t[]="abaabb";
const string q[]={"","a","ab","abb","aabb","aaabb","aaabbb","aaababb","aaababbb"};
int main() {
int T=rd();
while(T--) {
int n=rd(),K=rd();
if(K==1) {
printf("%d ",n);
rep(i,1,n)putchar('a');
putchar('\n');
} else if(K>2) {
printf("1 ");
rep(i,1,n)putchar(s[(i-1)%K]);
putchar('\n');
} else {
if(n<=8) {
int a=(n<=4)?(n<=2?1:2):3;
printf("%d ",a);
cout<<q[n]<<endl;
} else {
printf("4 ");
rep(i,1,n) {
putchar(t[(i-1)%6]);
}
putchar('\n');
}
}
}
}
CSUBQ:
const int N=5e5+11;
inline ll calc(int n){return 1LL*n*(n+1)/2;}
struct Info{int l,r;ll tot;};
int n;
struct SegTree{
struct Node{
int l,r,siz;
ll tot;
} t[N<<2];
#define mid (L+R>>1)
#define All 1,1,n
#define lson o<<1,L,mid
#define rson o<<1|1,mid+1,R
void push_up(int o){
t[o].l=t[o<<1].l+(t[o<<1].l==t[o<<1].siz)*t[o<<1|1].l;
t[o].r=t[o<<1|1].r+(t[o<<1|1].r==t[o<<1|1].siz)*t[o<<1].r;
t[o].tot=t[o<<1].tot+t[o<<1|1].tot-calc(t[o<<1].r)-calc(t[o<<1|1].l)+calc(t[o<<1].r+t[o<<1|1].l);
}
void build(int o,int L,int R,int v=1){
Node *x=&t[o];
x->siz=R-L+1;
if(L==R)x->tot=x->l=x->r=v;
else{
build(lson,v),build(rson,v);
push_up(o);
}
}
void modify(int o,int L,int R,int v,int al){
Node *x=&t[o];
if(L==R)x->tot=x->l=x->r=al;
else{
if(v<=mid)modify(lson,v,al);
else modify(rson,v,al);
push_up(o);
}
}
Info query(int o,int L,int R,int l,int r){
if(L==l&&R==r)return (Info){t[o].l,t[o].r,t[o].tot};
else{
if(r<=mid)return query(lson,l,r);
else if(l>mid)return query(rson,l,r);
else{
Info a=query(lson,l,mid),b=query(rson,mid+1,r),c;
c.l=a.l+(a.l==mid-l+1)*b.l,c.r=b.r+(b.r==r-mid)*a.r;
c.tot=a.tot+b.tot-calc(a.r)-calc(b.l)+calc(a.r+b.l);
return c;
}
}
}
inline ll ask(int l,int r){return query(All,l,r).tot;}
inline void upd(int v,int x){modify(All,v,x);}
}s1,s2;
int main(){
#ifdef flukehn
freopen("test.txt","r",stdin);
#endif
n=rd();
int q=rd(),L=rd(),R=rd();
s1.build(All),s2.build(All);
while(q--){
int o=rd(),x=rd(),y=rd();
if(o==1){
s1.upd(x,y<=R),s2.upd(x,y<L);
} else {
// assert(x<=y);
printf("%lld\n",s1.ask(x,y)-s2.ask(x,y));
}
}
}