当前位置: 首页 > news >正文

QOJ#12181. abc

QOJ#12181. abc

题意

给你一个包含 \(\texttt{a,b,c}\) 的字符串。求所有区间的权值和。一个区间的权值定义为区间内出现次数的字母的个数,减去出现次数最少的字母的个数。(出现次数不为 \(0\)

\(n \le 2 \times 10^5\)

思路

原式很难分讨。所以要先统一一下式子。

  • 对于包含 \(3\) 种不同字母的区间 \([l,r]\)

\[val_{l,r} = \frac{|c_a-c_b| + |c_b-c_c| + |c_c-c_a|}2 \]

  • 对于包含 \(2\) 种不同字母的区间 \([l,r]\),假设它包含 \(a,b\)

\[val_{l,r} = |c_a-c_b| \]

  • 对于包含 \(1\) 种不同字母的区间 \([l,r]\),没有贡献。

这里怎么线性维护,感觉还是有点困难的。

这样要维护什么就很显然了吧。首先贡献乘二以去掉分母。

一种比较简洁的维护方法是,枚举两个字母 \(A,B\)

  • 对于包含 \(A,B\) 的区间,计算 \(2|c_A - c_B|\)。这恰好满足包含两种不同字母的区间的贡献。
  • 对于包含三种字母的区间,要减去多余的贡献。计算 \(-|c_A - c_B|\)

我们枚举区间右端点 \(r\)

维护以 \(r\) 为右端点的区间的贡献。怎么从 \(r-1\) 转移过来。

加入 \(a_r\) 后,绝对值为 \(0,\pm1\) 的贡献需要变化。我们用 \(cnt_x\) 存差值(非绝对值)为 \(x\) 的区间个数。

因为不能左右移 \(cnt\) 数组。所以再记一个偏移量 \(tag\) 即可。

加入 \(a_r\) 后有可能要加入新的区间。直接加即可。

时间复杂度线性。

code

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace wing_heart {constexpr int N=2e5+7;int n;char s[N];int t[N];int cnt[N<<1],tag;ll ans;void solve(int a,int b) {memset(cnt,0,sizeof(cnt)); tag=0;int cl=0,cr=0;ll sl=0,sr=0;int sa=0,sb=0;int l=0;rep(r,1,n) {if(t[r]==a) cr+=cnt[-tag+N],sr+=cr,tag++,sl-=cl,cl-=cnt[-tag+N],sa++;if(t[r]==b) cl+=cnt[-tag+N],sl+=cl,tag--,sr-=cr,cr-=cnt[-tag+N],sb++;while(sa && sb) {++l;cnt[sa-sb-tag+N]++;if(sa-sb>0) cr++, sr+=sa-sb;if(sa-sb<0) cl++, sl+=sb-sa;if(t[l]==a) --sa;if(t[l]==b) --sb;}ans+=2*(sl+sr);}memset(cnt,0,sizeof(cnt)); tag=0;cl=0,cr=0;sl=0,sr=0;sa=0,sb=0;int sc=0,c=3^a^b;l=0;rep(r,1,n) {if(t[r]==a) cr+=cnt[-tag+N],sr+=cr,tag++,sl-=cl,cl-=cnt[-tag+N],sa++;if(t[r]==b) cl+=cnt[-tag+N],sl+=cl,tag--,sr-=cr,cr-=cnt[-tag+N],sb++;if(t[r]==c) sc++;while(sa && sb && sc) {++l;cnt[sa-sb-tag+N]++;if(sa-sb>0) cr++, sr+=sa-sb;if(sa-sb<0) cl++, sl+=sb-sa;if(t[l]==a) --sa;if(t[l]==b) --sb;if(t[l]==c) --sc;}ans-=sl+sr;}}void main() {sf("%d",&n);sf("%s",s+1);rep(i,1,n) t[i] = s[i]-'a';solve(0,1), solve(1,2), solve(2,0);pf("%lld\n",ans/2);}
}
int main() {#ifdef LOCALfreopen("in.txt","r",stdin);freopen("my.out","w",stdout);#endifwing_heart :: main();
}
http://www.hskmm.com/?act=detail&tid=37137

相关文章:

  • 2025年10月ai优化推荐:全维度对比评价助你精准决策
  • 2025年10月ai搜索排名优化推荐:主流榜单对比与避坑指南
  • 2025 年润滑油厂家最新推荐榜,聚焦品牌技术实力与市场口碑深度解析润滑油回用 / 液压油润滑油过滤 / 液压油润滑油净化公司推荐
  • dokuwiki制作侧边栏
  • MySQL的这6大雷区,大部分人都会踩中!
  • 实验台厂家哪家好?2025年度权威推荐榜单揭晓!
  • 2025 年办公家具厂家最新推荐榜,绿色智造与服务能力双重维度下的优质品牌解析
  • 1115. 交替打印FooBar
  • 2025 年透气阀厂家最新推荐榜:深度剖析行业内优质企业技术实力与市场口碑,筛选高性能可靠品牌
  • 2025年10月AI搜索营销推荐:头部企业合作口碑榜
  • 函数编程(Leo)
  • P8060 [POI 2003] Sums
  • 2025年杭州电商代运营机构口碑榜:技术实力与成功案例深度分析
  • 【A】Sakura Tears
  • 资源分享--豪氏象棋教程
  • 2025年10月AI搜索营销推荐:主流服务商排行榜与避坑指南
  • 内网应用端口使用哪个范围的比较安全
  • 2025年10月AI搜索优化推荐:市场报告与全维度选择指南
  • Vue3+ts+pinia实现活跃的tab栏
  • 2025年10月AI搜索优化推荐:主流榜单对比与避坑指南
  • 排序算法学习笔记
  • 异常值检测算法学习
  • 2025 年国内喷雾干燥机最新推荐排行榜:聚焦优质品牌,助力企业精准选设备造粒/工业喷雾/陶瓷喷雾/制粒/奶粉喷雾干燥机厂家推荐
  • Python环境教程(一)-环境入门之pip conda
  • AI股票预测分析报告 - 2025年10月23日
  • SQL Server 2008 R2 升级补丁需要注意的问题
  • Maven的使用(Leo)
  • 标题
  • 数字化实战:医疗器械行业售后工程师如何借CRM实现高效运维​
  • 20251020_QQ_Cipher