选举「elections」
前言
震惊,\(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 解释】
查询 \(\texttt{1:CCCTTTTTTCC}\)
查询 \(\texttt{2:TTTTTT}\)
查询 \(\texttt{3:CCCTTT}\)
【数据范围与约束】
测试点编号 | \(N,Q\) |
---|---|
\(1\)~\(5\) | \(N,Q\)\(\le 2\)$ \times 10^3$ |
\(6\)~\(15\) | \(N,Q\)\(\le 7\)$ \times 10^4$ |
\(16\)~\(25\) | \(N,Q\)\(\le 5\)$ \times 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],'\n');
}
return 0;
}