前言
震惊,(O(n^2))暴力竟可艹过64pts!
于是水一篇题解
有什么必然联系吗?
题目
【题目描述】
有一个长度为(N)的字符串(S[1...N]),它仅由C
和T
两种字母组成。
现在有(Q)个查询,每个查询包含两个整数(L)和(R),表示:设新字符串(S'=S[L..,R]) ,至少在(S')中
要删除多少个字符,才能保证:对于(S')的每一个前缀与每一个后缀,其C
的数量都不小于T
的数
量。
【输入格式】
第一行有一个整数(N)。
第二行有一个长度为(N)的字符串(S)。
第三行有一个整数(Q)。
在接下来的(Q)行中,每行有两个整数(L)和(R),表示一组查询。
【输出格式】
对于每组查询输出一行,表示至少在(S')中要删除多少个字符,才能保证题面要求。
【样例1 输入】
11
CCCTTTTTTCC
3
1 11
4 9
1 6
【样例1 输出】
4 6 3
【样例1 解释】
查询 ( exttt{1:CCCTTTTTTCC})
查询 ( exttt{2:TTTTTT})
查询 ( exttt{3:CCCTTT})
【数据范围与约束】
测试点编号 | (N,Q) |
---|---|
(1)~(5) | (N,Q)(le 2)$ imes 10^3$ |
(6)~(15) | (N,Q)(le 7)$ imes 10^4$ |
(16)~(25) | (N,Q)(le 5)$ imes 10^5$ |
讲解
把相同相邻字符捆起来然后暴力+优秀常数+信仰O2=64pts v
这作者太懒了吧
代码
#define lc (x<<1)
#define rc (x<<1|1)
struct SegmentTree
{
struct node
{
int MAX,MIN,MF;
node(){}
node(int MAX1,int MIN1,int MF1){
MAX = MAX1;
MIN = MIN1;
MF = MF1;
}
node operator + (const node &A)const{
return node(Max(MAX,A.MAX),Min(MIN,A.MIN),Max(Max(MF,A.MF),A.MAX - MIN));
}
}t[MAXN << 2];
void Build(int x,int l,int r)
{
if(l == r) {t[x] = node(s[l],s[l],0);return;}
int mid = (l+r) >> 1;
Build(lc,l,mid);Build(rc,mid+1,r);
t[x] = t[lc] + t[rc];
}
node Query(int x,int l,int r,int ql,int qr)
{
if(ql <= l && r <= qr) return t[x];
int mid = (l+r) >> 1;
if(ql <= mid && mid+1 <= qr) return Query(lc,l,mid,ql,qr) + Query(rc,mid+1,r,ql,qr);
if(ql <= mid) return Query(lc,l,mid,ql,qr);
return Query(rc,mid+1,r,ql,qr);
}
}st;
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read();
scanf("%s",a+1);
for(int i = 1;i <= n;++ i) s[i] = s[i-1] + (a[i] == 'C' ? 1 : -1);
st.Build(1,0,n);
for(int Q = Read(); Q ;-- Q)
{
int l = Read(),r = Read();
Put(st.Query(1,0,n,l-1,r).MF - s[r] + s[l-1],'
');
}
return 0;
}