远古人的历史(history)

题意:
给定一个由 * 和 | 组成的字符串,其中 * 必须在 | 前面。
数值是 *的数量 × 5 加上 |的数量 × 1。
每次修改将某个位置改成 ?,表示这个位置可以填 * 或 |,但要保证书写规范(即所有 * 在所有 | 前面)。
每次修改后都要输出所有可能的数字的数值和。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
string s;
int q;
int f[N];// 记录每个位置当前是什么:0表示?,1表示*,2表示|
int main(){
	cin >> s >> q;
	s=' '+s;
	int len=s.size()-1;
	int r=0,l=len+1;//r:最后一个'*',l:第一个'|'
	for(int i=1;i<=len;i++){
		if(s[i]=='*'){
			f[i]=1;
			r=i;
		}else if(s[i]=='|'){
			f[i]=2;
			if(l==len+1) l=i; 
		}
	}
	while(q--){
		int x;
		cin >> x;
		f[x]=0;
		if(r==x){
			while(r>0&&f[r]!=1) r--;
		}
		if(l==x){
			while(l<=len&&f[l]!=2) l++;
		}//维护区间
		ll L=r,R=l-1;
		if(L>R) cout << "0\n";
		else{
			ll ans=R-L+1;
			ll sum=(L+R)*ans/2;
			ll tot=4*sum+len*ans;
			cout << tot << '\n';
		}
	}
    return 0;
}

此代码思路为:
1.设:
R=最后一个 * 的位置
L=第一个 | 的位置
区间 [R+1, L-1] 中每个位置可以填或|,但要保持规范。
有效字符串的个数=L-R
维护L,R每次位数发生变化,都去更新
2.计算
对于每个位置k,有前k个'
',后n-k个'|'
这一串数值为:
数值= 5(的个数)+1(|的个数)
=5k+n-k
=n+4k
后用等差数列求和
总和=(k=L 到 R) n+(k=L 到 R)4k
=n
(R-L+1)+ 4(k=L 到 R)k
总和 =n
cnt+4(L+R)cnt/2
=cntn+2(L+R)*cnt
就是

ll ans = R - L + 1;           // cnt = 区间长度
ll sum = (L + R) * ans / 2;   // 等差数列求和 (k=L 到 R) k
ll tot = 4 * sum + n * ans;   // 4*sum + n*cnt

总复杂度为O(q+n)

posted @ 2026-07-05 17:14  zhangyirui  阅读(8)  评论(0)    收藏  举报