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

设第i个字母的权值为1<<i,则一个可重集合可以重排为回文串,当且仅当这个集合的异或和x满足x==x&-x,用莫队维护区间内有多少对异或前缀和,异或后满足x==x&-x,这样端点移动的代价为字符集大小+1=27,因此时间复杂度为$O(27n\sqrt{m})$

#include<cstdio>
#include<cmath>
#include<algorithm>
char buf[3000000],*ptr=buf-1;
int _(){
    int x=0,c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
typedef unsigned int u32;
const int P=2939999,N=61007;
int n,q,xs[N][27];
int hx[P][2],idp=0;
int getid(int x){
    int w=x%P;
    while(hx[w][1]){
        if(hx[w][0]==x)return hx[w][1];
        if((w+=12347)>=P)w-=P;
    }
    hx[w][0]=x;
    return hx[w][1]=++idp;
}
u32 as[N],pos[N],B,ans=0,t[N*27];
struct Q{
    int l,r,id;
}qs[N];
bool operator<(Q a,Q b){
    if(pos[a.l]!=pos[b.l])return pos[a.l]<pos[b.l];
    if(a.r!=b.r)return (a.r<b.r)^(pos[a.l]&1);
    return a.id<b.id;
}
void ins(int*x){
    for(int i=0;i<=26;++i)ans+=t[x[i]];
    ++t[x[26]];
}
void del(int*x){
    --t[x[26]];
    for(int i=0;i<=26;++i)ans-=t[x[i]];
}
int main(){
    fread(buf,1,sizeof(buf),stdin)[buf]=0;
    n=_();q=_();
    B=(n+1)/sqrt(q+1)+1;
    for(int i=0;i<=n;++i)pos[i]=i/B;
    while(*ptr<‘a‘)++ptr;
    for(int i=1;i<=n;++i)xs[i][26]=xs[i-1][26]^1<<*ptr++-‘a‘;
    for(int i=0;i<=n;++i){
        for(int j=0;j<26;++j)xs[i][j]=xs[i][26]^1<<j;
    }
    for(int i=0;i<=n;++i){
        for(int j=0;j<=26;++j)xs[i][j]=getid(xs[i][j]);
    }
    for(int i=0;i<q;++i){
        qs[i].l=_()-1;
        qs[i].r=_();
        qs[i].id=i;
    }
    std::sort(qs,qs+q);
    int L=1,R=0;
    for(int i=0;i<q;++i){
        int l=qs[i].l,r=qs[i].r;
        while(L>l)ins(xs[--L]);
        while(R<r)ins(xs[++R]);
        while(L<l)del(xs[L++]);
        while(R>r)del(xs[R--]);
        as[qs[i].id]=ans;
    }
    for(int i=0;i<q;++i)printf("%u\n",as[i]);
    return 0;
}
时间: 2024-10-03 22:19:12

bzoj 4866: [Ynoi2017]由乃的商场之旅的相关文章

bzoj 3598: [Scoi2014]方伯伯的商场之旅【数位dp】

参考了这个http://www.cnblogs.com/Artanis/p/3751644.html,好像比一般方法好写 大概思想就是先计算出把所有石子都合并到1位置的代价,这样显然有一些是不优的,然后再分别计算把合并到1的石子合并到p,能优化多少 这个计算就是枚举2到tot位,对于每一位计算挪到这位能被优化的数最多能被优化多少,因为合并点右移的代价是sum[w]-(sum[n]-sum[w]),所以只要这个为负数就退出即可 #include<iostream> #include<cst

BZOJ3598: [Scoi2014]方伯伯的商场之旅

方伯伯的商场之旅 输入格式: 输入仅有1 行,包含3 个用空格分隔的整数L,R,K,表示商场给方伯伯的2 个整数,以及进制数 输出格式: 输出仅有1 行,包含1 个整数,表示最少的代价. 样例输入: 3 8 3 样例输出: 5 数据范围: 时间限制: 3s 空间限制: 64M 具体思路:数位DP 先假装所有数都转移到第一位上, 然后扫一下其他位,把对答案有益的加上 AC代码 #include<bits/stdc++.h> using namespace std; #define int lon

「SCOI2014」方伯伯的商场之旅

「SCOI2014」方伯伯的商场之旅 题目描述 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 \(K\) 进制后的第 \(j\) 位. 现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 \(L,R\).方伯伯要把位置在 \([L, R]\) 中的每个人的石子都合并成一堆石子.每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价

[BZOJ]4810: [Ynoi2017]由乃的玉米田

Time Limit: 30 Sec  Memory Limit: 256 MB Description 由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3选出的这两个

bzoj 4811: [Ynoi2017]由乃的OJ

树链剖分,用zkw线段树维护每条链两个方向上对每一位的变换情况,由于位数较少,可以用两个unsigned long long表示 #include<cstdio> typedef unsigned long long u64; const int N=100007; char buf[N*100],*ptr=buf-1; int _(){ int x=0,c=*++ptr; while(c<48)c=*++ptr; while(c>47)x=x*10+c-48,c=*++ptr;

bzoj 3598 [ Scoi 2014 ] 方伯伯的商场之旅 ——数位DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3598 数位DP...东看西看:http://www.cnblogs.com/Artanis/p/3751644.html     https://www.cnblogs.com/MashiroSky/p/6399095.html 好巧妙的思路啊!这样统计的东西就变得很简单了: 好美的 dfs!数位DP用 dfs 好像能变得很清楚. 代码如下: #include<iostream> #in

bzoj 4810: [Ynoi2017]由乃的玉米田 莫队 bitset

bitset大概就是让你轻松建立一个很长的二进制数来存东西,并提供了快捷的操作和优美的常数. #include <bitset> bitset <32> b;32为长度 需要引用头文件,定义一个bitset. stl的东西,所以从0开始. 支持左右移. 支持下标访问修改. b.any() b中是否存在置为1的二进制位 b.none() b中不存在置为1的二进制位 b.count() b中置为1的二进制位的个数 b.size() b中二进制位的个数 b[pos] 访问b中在pos处的

[SCOI2014]方伯伯的商场之旅

Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的第 j 位. 现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 L,R.方伯伯要把位置在 [L, R] 中的每个人的石子都合并成一堆石子.每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价是移动的石子数量 * 移动的距离.商场承诺,方伯伯只要完成任务,就给他一些椰子,

【SCOI2014】【BZOJ3598】方伯伯的商场之旅(数位dp)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3598 题意: 对于一个数x,它含有一些小石子,每个石子的值为a[i](a[i]为x在k进制下的第i位),选一个石子的位置pos使得sum(a[i] * abs(i-pos))最小. 求出[L,R]中所有数这个值的和. 题解: 对于一个数,我们枚举最优位置时,可以发现从i->i+1的变化为+pre[i]-suf[i+1](分别为前缀和与后缀和). 30%的暴力分,我们枚举[L,R]中的数,然