bzoj 4866: [Ynoi2017]由乃的商场之旅

6人阅读 评论(0) 收藏 举报
分类:

题意

给你一个序列
每一次给你一个区间[l,r],问你这里面有多少个子区间满足,里面的字母经过排序可以变成回文

前言

以前做的一道题,但是写在题表里面了
bzoj 乱刷计划
感觉这题挺好的,于是特地拿出来复习一下

题解

首先,我们容易发现,如果我们给每一个字母分配一个权值
a就是1b就是2c就是3。。。x就是2i
然后这样就是问有多少个子区间满足它这一段的异或和为0或者若干次幂
我们考虑用莫队来做这题
一个比较显然的暴力莫队是26nn的,详见beginend,做法很简单,但是不是很好写
并且我们发现,这个的话,我们维护辅助数组的话是O(1)的,但是维护答案是O(26)
这个做法不是特别的好优化,于是我们可以把这个方法改造成一个O(26)维护辅助数组,然后维护答案是O(1)
这个的话,我们把辅助数组的定义改为,如果插入这个数的话,会贡献多少答案就可以了
每一次新加入一个状态x,就枚举一个2i,然后让x^(2i)这个位置++
然后就可以做到O(26)维护辅助数组,然后维护答案是O(1)
这样由什么好处呢?
我们可以发现这个复杂度并不平衡
于是我们可以平衡复杂度
具体地说,我们可以让莫队的时候,对于l端点在用一个块的答案,让r单调递增地扫过去
然后每一个询问,再暴力扫一次l到左端点
这样的话,我们可以发现这样的话,移动左端点是O(1)的,移动右端点是O(26)
根据均值不定式修改块的大小就可以做到O(n26n)
但是这样的话还有一种情况没有处理,那就是左端点之间的答案没有计算
这个没有关系,我们这个可以预处理啊
我们预处理一下一个点i到这个块的右端点的答案就可以了
用这个方法就可以吧26放到根号里面去了
同样的,如果你遇到一个维护辅助数组是O(S)的,答案是O(1)的,都可以用这个方法来平衡复杂度
然后一般来说,如果维护辅助数组是O(1)的,但是维护答案是O(S),你都可以用特殊的方法把形式变成上面这种
这里只给出后面一个方法的代码,前面比较慢的写法大同小异,我就不贴了
CODE:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=60005;
inline 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;
}
int n,m;
char ss[N];
int p[N];
int size;
int belong[N];
int ha[N];//异或前缀和
unsigned short f[1<<26];
int R[N];
void Ins (int x,int o)
{
    x=ha[x];
    f[x]+=o;
    for (int u=0; u<26; u++) f[x^p[u]]+=o;

}
struct qq
{
    int l,r,id;
} q[N];
bool cmp (qq a,qq b)
{
    return belong[a.l]==belong[b.l]?a.r<b.r:a.l<b.l;
}
LL Ans[N];
int Bl(int l,int r)
{
    int ans2=0;
    for(int i=l; i<=r; ++i)
        Ins(i-1,1),ans2+=f[ha[i]];
    for(int i=l; i<=r; ++i) Ins(i-1,-1);
    return ans2;
}
LL ans,pre[N];
int main()
{
    n=read();
    m=read();
    size=sqrt(26*n);
    //size=1;
    for (int u=1; u<=n; u++) belong[u]=(u-1)/size+1;
    p[0]=1;
    for (int u=1; u<26; u++) p[u]=p[u-1]<<1;
    scanf("%s",ss+1);
    int tot=(n-1)/size+1;
    for (int u=1; u<=n; u++) ha[u]=ha[u-1]^p[ss[u]-'a'];
    for (int u=1; u<=tot; u++)
    {
        R[u]=min(n,u*size);
        ans=0;
        for (int i=R[u]; i>R[u-1]; i--)
        {
            Ins(i,1),ans=ans+f[ha[i-1]],pre[i]=ans;
        }
        for (int i=R[u]; i>R[u-1]; i--)  Ins(i,-1);
    }
    for (int u=1; u<=m; u++) q[u].l=read(),q[u].r=read(),q[u].id=u;
    sort(q+1,q+1+m,cmp);
    int last=0;
    int r=0;//右端点在哪里
    for (int u=1; u<=m; u++)
    {
        if (belong[q[u].l]!=last)//扩过了这一块
        {
            for (int i=R[last]; i<r; i++) Ins(i,-1);
            last=belong[q[u].l];
            r=R[last];
            ans=0;
        }
        if (belong[q[u].l]==belong[q[u].r]) Ans[q[u].id]=Bl(q[u].l,q[u].r);
        else
        {
            while(r<q[u].r) ++r,Ins(r-1,1),ans+=f[ha[r]];
            LL ans2=0;
            Ins(r,1);
            Ins(R[last],-1);
            for(int j=q[u].l; j<=R[last]; ++j) ans2+=f[ha[j-1]];
            Ans[q[u].id]=ans+pre[q[u].l]+ans2;
            Ins(r,-1);
            Ins(R[last],1);
        }
    }
    for (int u=1; u<=m; u++)
        printf("%lld\n",Ans[u]);
    return 0;
}
查看评论

[莫队 分块] BZOJ 4866 [Ynoi2017]由乃的商场之旅

这个 只会莫队乱搞 自己YY下 复杂度O(n26∗n−−−−−√)O(n\sqrt{26*n}) 成功贴时限过加时间垫底#include #include #include #include us...
  • u014609452
  • u014609452
  • 2017-04-24 20:58:41
  • 692

BZOJ4866: [Ynoi2017]由乃的商场之旅 莫队

http://www.lydsy.com/JudgeOnline/problem.php?id=4866 询问一个字符串区间内有多少子区间重排后能形成回文串。 由于字符集只有26,可以给每个字母分配...
  • Mima_Reincarnation
  • Mima_Reincarnation
  • 2017-06-08 20:21:37
  • 365

bzoj 4866: [Ynoi2017]由乃的商场之旅 莫队算法

题意给出一个长度为n的由小写字母组成的字符串,每次询问一个区间内有多少连续子串重新排列后可以得到一个回文串。 n,q...
  • qq_33229466
  • qq_33229466
  • 2017-04-26 19:40:33
  • 505

4866: [Ynoi2017]由乃的商场之旅

4866: [Ynoi2017]由乃的商场之旅Time Limit: 20 Sec Memory Limit: 164 MB Submit: 192 Solved: 47 [Submit][S...
  • CRZbulabula
  • CRZbulabula
  • 2017-05-03 17:03:41
  • 496

bzoj4810 [Ynoi2017]由乃的玉米田 莫队+bitset

Description由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美。这排玉米一共有N株,它们的高度参差不齐。 由乃认为玉米田不美,所以她决定出个数据结构题这个题是这样的: 给你一个序...
  • qq_35866453
  • qq_35866453
  • 2017-04-18 21:03:12
  • 295

BZOJ4012: [HNOI2015]开店 重链剖分 可持久化线段树

http://www.lydsy.com/JudgeOnline/problem.php?id=4012 两点间距离:深度之和-2×LCA深度 http://blog.csdn.net/mima_...
  • Mima_Reincarnation
  • Mima_Reincarnation
  • 2017-06-08 19:53:25
  • 656

[bzoj4867] [Ynoi2017]舌尖上的由乃

题目大意给定一棵n个节点的树,边有边权。m个操作:1. 给一条边边权加k;2.询问一棵子树第k小的深度。 修改操作的k和最初的边权不超过一个给定的常数lenn,m≤100000 len≤10分析...
  • WorldWide_D
  • WorldWide_D
  • 2017-09-02 22:13:20
  • 340

bzoj 4811: [Ynoi2017]由乃的OJ (树链剖分)

题目描述传送门题解这道题与Noi2014起床困难综合症 十分类似。同样的每一位也是互补影响的,那么最基础的思路就是对于每一位分开维护,对于树进行树链剖分,对于线段树中的区间维护以0,1打头从左到右和从...
  • clover_hxy
  • clover_hxy
  • 2017-04-16 09:49:43
  • 448

BZOJ 4811([Ynoi2017]由乃的OJ-树链剖分)

Description由乃正在做她的OJ。现在她在处理OJ上的用户排名问题。OJ上注册了n个用户,编号为1~”,一开始他们按照编号 排名。由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号...
  • nike0good
  • nike0good
  • 2017-04-29 19:06:32
  • 497

BZOJ4811 [Ynoi2017]由乃的OJ

显然用LCT维护一下经过一条链之后每一位原来是1会变成什么原来是0会变成什么即可 这样的话LCT复杂度是n log n * k的,链剖是n log^2 n * k的,都过不了 考虑把这个k给去掉,...
  • neither_nor
  • neither_nor
  • 2017-04-07 15:04:09
  • 1033
    个人资料
    持之以恒
    等级:
    访问量: 5万+
    积分: 5576
    排名: 5902
    最新评论