首页 > 其他分享 >CF1750E 题解

CF1750E 题解

时间:2022-11-11 21:46:02浏览次数:62  
标签:int 题解 sum mid CF1750E 括号 text

没看懂官方社论,只好自力更生了。

我们很容易知道,对于一段区间,其代价就是多余的括号数(左右括号中多出来的括号数)加上不属于多余括号,但没有匹配的左或右括号数。即左括号总量与右括号总量的最大值减去匹配括号对数。

匹配括号对数很容易线性求出,现在关键就是怎么维护所有区间的左括号总量减去右括号总量。记 \(b\) 左括号在一段前缀中的出现次数,\(c\) 为右括号在一段前缀中的出现次数,那么我们要求的就是 \(\sum_{l=1}^n\sum_{r=l}^n\max(b_r-b_{l-1},c_r-c_{l-1})\)。我一开始以为是扫右端点加线段树维护,但是想了很久很久都没有想出来。后来我 偷偷看了 yyyyxh 的场切代码,发现他用分治做,大受启发, 想到了把这个式子拆成两部分:

\[\sum_{l=1}^n\sum_{r=l}^n[b_r-b_{l-1}\ge c_r-c_{l-1}](b_r-b_{l-1})+[b_r-b_{l-1}<c_r-c_{l-1}](c_r-c_{l-1}) \]

为了更方便地维护,我们对式子做一下微调:

\[\sum_{l=0}^{n-1}\sum_{r=l+1}^n[b_r-c_r\ge b_l-c_l](b_r-b_l)+[b_r-c_r<b_l-c_l](c_r-c_l) \]

所以就转化为了一个偏序问题,可以用分治来维护。具体地,处理区间 \([l,r]\) 时,递归处理 \([l,\text{mid}]\) 和 \([\text{mid}+1,r]\)。把 \([l,\text{mid}]\) 扫一遍作为左端点统计,同时用一个指针维护右半部分第一个或最后一个 \(b-c\) 满足偏序关系的点,然后分别用前缀和和后缀和计算贡献就行了。

时间复杂度为 \(O(n\log n)\)。但是好像跑得和两只 log 的二分做法一样快。


后来看了看 洛谷上的题解,再次感到了自己的弱小。

洛谷的题解前面的思路和我一样。但是在遇到 \(\max(L,R)\) 时,没有把它用分类讨论强制拆开,而是化成了 \(\dfrac{L+R+|L-R|}{2}\) 然后轻松计算,只要一次排序就能爆切。数学方法就是强!


下面是我写的分治做法。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int N=2e5+5;
struct Node{
	int b,c,d;Node(){b=0;c=0;d=0;}
	bool operator<(const Node&O)const{return d<O.d;}
}t[N];char s[N];int n,sta[N];ll ans,sb[N],sc[N];
inline void solve(int l,int r){
	if(l==r)return;
	int mid=l+r>>1;solve(l,mid);solve(mid+1,r);
	sb[r+1]=0;sc[mid]=0;
	for(int i=mid+1;i<=r;i++)sc[i]=sc[i-1]+t[i].c;
	for(int i=r;i>mid;i--)sb[i]=sb[i+1]+t[i].b;
	for(int i=l,p=mid+1;i<=mid;i++){
		while(p<=r&&t[p].d<t[i].d)p++;
		ans+=sb[p]-(ll)t[i].b*(r-p+1);
		ans+=sc[p-1]-(ll)t[i].c*(p-1-mid);
	}
	inplace_merge(t+l,t+mid+1,t+r+1);
}
inline void ct(){
	scanf("%d%s",&n,s+1);ans=0;
	for(int i=1,top=0;i<=n;i++){
		t[i]=t[i-1];
		if(s[i]=='('){
			sta[++top]=i;t[i].b++;
		}else{
			t[i].c++;
			if(top)ans-=(ll)sta[top--]*(n-i+1);
		}
		t[i].d=t[i].b-t[i].c;
	}
	solve(0,n);
	cout<<ans<<'\n';
}
int main(){
	int T;cin>>T;while(T--)ct();
	return 0;
}

标签:int,题解,sum,mid,CF1750E,括号,text
From: https://www.cnblogs.com/hihihi198/p/16882108.html

相关文章

  • CF1252K Addition Robot 题解
    题目链接思路对于\(A=A+B\),\(B=A+B\)这种的递推式可以考虑矩阵加速递推,可得:\[\left(\begin{matrix}A+B&B\end{matrix}\right)=\left(\begin{ma......
  • P5443 [APIO2019] 桥梁 题解
    容易得出一种暴力算法:将询问按\(w\)排序,将没有修改的边按\(d\)排序。对于每个询问\((t_i,s_i,w_i)\),做两部分操作(这里\(t\)是时间的意思):将没有修改的边中满足\(d......
  • P1587 [NOI2016] 循环之美 题解
    P1587[NOI2016]循环之美这道题我推到后面推不下去了,最后还是看了题解。还是切不了这种题唉。前置知识:杜教筛开始时看不出什么,我们先用经验和手玩来找一下规律。我们......
  • P6628 [省选联考 2020 B 卷] 丁香之路 题解
    图论、贪心好题。枚举每一个朋友,设一个朋友从\(s\)出发,到\(t\)结束。那么如果用边来表示其行动轨迹,必然是\(s,t\)有奇数度,其它点均为偶数度。如果在\(s,t\)之间连......
  • CF464D World of Darkraft - 2 题解
    期望好题,可以帮助我们更加深入地了解期望。由于\(k\)种装备相同,所以只要计算卖掉一种装备得到的金币期望乘以\(k\)就行了。为了避免讨论当前状态的概率,期望DP通常......
  • CF1316E Team Building 题解
    可能更好的阅读体验题目传送门题目大意传送门你需要组建一支排球队。为了组织一支排球队,你需要为队伍里的\(p\)个不同的位置,从\(n\)个人中选出\(p\)个人,且每个位......
  • CF1735E题解
    钦定\(p_1=0,p_2>0\),不难证明如果有解则一定存在\(p_2>p_1\)的解。考虑枚举和\(d_{1,1}\)是相同楼房,则\(p_2\)对于每一种情况有两种可能的位置:\(d_{1,1}+d_{2,i}\)......
  • P3188 [HNOI2007]梦幻岛宝珠 题解
    一道不错的dp题,下令原背包容量为\(m\)。注意到\(w_i=a\times2^b\)中\(a,b\)都比较小,尝试按照\(a\)或者\(b\)分组然后合并,但是显然如果我们按照\(a\)分组就......
  • 汉诺塔问题及其变种问题解法(cpp版本)
    普通汉诺塔问题1.问题描述有三个柱子A、B、C,A柱子上有n个圆盘,圆盘的大小不等,大圆盘的在下,小圆盘的在上。将A柱子上的圆盘全部移动到C柱子上。每次只能移动一个圆盘,而且......
  • 【题解】P2260 [清华集训2012]模积和(数学,整除分块)
    【题解】P2260[清华集训2012]模积和比较简单的一道推式子的题。(清华集训居然会出这种水题的吗)题目链接P2260[清华集训2012]模积和题意概述求\[\sum_{i=1}^{n}\sum......