[USACO22DEC] Palindromes P 题解

T3 [USACO22DEC] Palindromes P

郝题。首先考虑给定一个串 S 怎么求出要换多少次。

易得,不可能交换两个本来就相同的字符。不妨观察 G 的回文关系,一对 G 回文当且仅当第一个 G 前面的 H 数量等于第二个 G 后面的 H 的数量。换句话说,若当前的串 [l,r],其中有一对 G 的位置为 (a,b),则将这一对 G 归位的花费为:

|(a+b)(l+r)|

简单手模应该不难得到。要注意特殊情况:

  • 若串长为偶数但 G 的个数为奇数,不可能为回文串,1 走人;
  • 否则一定存在一个 G 在正中间的位置,计算 |pos(l+r)/2|

所以我们就有一个 O(n3) 的暴力,其中 O(n2) 枚举子串,O(n) 计算答案。类似一个区间 DP 的复杂度,由于跑不满,可以通过 n2000 的数据,实测 36pts。

一般来说想到这里就差不多了。

我们发现可以转变转移方式,由中间向两边扩展。先枚举 i 作为中点,神奇地用树状数组维护 l+r 的值统计答案,然后向左向右扩展之后,再将新的 l+r 扔进树状数组。注意到原来有绝对值的符号,所以还需要维护 l+r 和的个数,算出 <l+r>l+r 的个数,就是一个 O(n2logn) 的做法。题解区还有 O(n2) 的做法。

感觉重点还是在于发现这个式子。

#include<bits/stdc++.h>
#define lowbit(x) (x&-x)
using namespace std;

using ll=long long;
constexpr int MAXN=7505;
int t[MAXN],n;
string s;
struct BIT{
	ll c[MAXN<<1];
	void add(int x,int k){
		while(x<=n<<1)c[x]+=k,x+=lowbit(x);
	}
	ll sum(int x){
		ll res=0;
		while(x)res+=c[x],x-=lowbit(x);
		return res;
	}
	void clear(){
		memset(c,0,sizeof(c));
	}
}t1,t2;

int main(){
	ios::sync_with_stdio(0);
	cin.tie(nullptr),cout.tie(nullptr);
	cin>>s;
	n=s.size();
	s=' '+s;
	int c=0;
	for(int i=1;i<=n;++i)if(s[i]=='G')t[++c]=i;
	t[c+1]=n+1;
	ll ans=0,sum=0,lans=0;
	for(int i=1;i<=c;++i){
		int lf=i,rf=i;
		while(lf&&rf<=c){
			int fk=t[lf]+t[rf];
			if(lf^i){
				t1.add(fk,fk),t2.add(fk,1);
				sum+=fk;
				++lans;
			}
			for(int l=t[lf];l>t[lf-1];--l)
				for(int r=t[rf];r<t[rf+1];++r){
					if((r-l+1)%2==0){
						--ans;
						continue;
					}
					ll p=t2.sum(l+r-1),q=t1.sum(l+r-1);
					ans+=abs((l+r)/2-t[i]);
					ans+=(p*(l+r)-q)+(sum-q)-(lans-p)*(l+r);
				}
			--lf,++rf;
		}
		sum=lans=0;
		t1.clear(),t2.clear();
	}
	for(int i=1;i<c;++i){
		int lf=i,rf=i+1;
		while(lf&&rf<=c){
			int fk=t[lf]+t[rf];
			t1.add(fk,fk),t2.add(fk,1);
			sum+=fk;
			++lans;
			for(int l=t[lf];l>t[lf-1];--l)
				for(int r=t[rf];r<t[rf+1];++r){
					ll p=t2.sum(l+r-1),q=t1.sum(l+r-1);
					ans+=(p*(l+r)-q+(sum-q)-(lans-p)*(l+r));
				}
			--lf,++rf;
		}
		sum=lans=0;
		t1.clear(),t2.clear();
	}
	cout<<ans<<'\n';
	return 0;
}
posted @   Laoshan_PLUS  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示