Codeforces 990C (模拟+组合数学)
题面:
分析:
此题O(n2l)" role="presentation" style="position: relative;">O(n2l)O(n2l)模拟肯定是会超时的(l为所有字符串总长)
我们想到对字符串进行一定的预处理,可以快速计算匹配
我们设每一个(的值为1,)的值为-1,规定
若只有)括号多了x个,则l[i]=r[i]=-x<0
若只有(括号多了x个,则l[i]=r[i]=x>0
那么如何求l[i],r[i]的值呢?
从左到右扫描字符串,用一个变量cnt,统计和
则cnt的最小值=l[i],最终的值=r[i]
若(和)都有多余,则必须接两个字符串,不符合条件,所以计算时应该直接跳过这些字符串,不用考虑
要理解这句话,请看下面的模拟过程
)()
字符串下标(0开始) 0 1 2
cnt值 -1 0 -1
l[i]=-1,说明左边需要一个(括号来匹配 (>=0即不需要)
r[i]=-1,说明右边不需要(<=0即不需要),而左边需要一个(括号
我们以all[i]来hash,哈希表的第 x位存储了所有r[i]=x的字符串的l[i]
但要注意的是,由于负数的原因,数组下标要人为加上一个数addv来存储
为了防止一对字符串被算两次,我们规定字符串只能接在右边,我们枚举字符串时要先保证l[i]>=0才能接,而l[i]<0的只能接在其他字符串右边
对于一个l[i]>=0的字符串i,我们寻找接在它右侧能匹配的字符串,所以我们在哈希表的−r[i]" role="presentation" style="position: relative;">−r[i]−r[i]位置寻找l[i]值为−r[i]" role="presentation" style="position: relative;">−r[i]−r[i]的字符串
比如:()(的l[i]=0,r[i]=1,我们则要寻找r[i]=l[i]=-1,即只多了一个)括号的字符串
用二分查找统计值为−r[i]" role="presentation" style="position: relative;">−r[i]−r[i]的字符串的个数,答案+=值为−r[i]" role="presentation" style="position: relative;">−r[i]−r[i]的字符串的个数
预处理时间复杂度O(l)" role="presentation" style="position: relative;">O(l)O(l) (l为所有字符串总长)
二分查找时间复杂度O(nlog2l)" role="presentation" style="position: relative;">O(nlog2l)O(nlog2l)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define addv 300005
#define maxn 2*addv
using namespace std;
int n;
char str[maxn];
int cnt;
int l[maxn];
int r[maxn];
vector<int>table[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",str);
int len=strlen(str);
l[i]=maxn;
cnt=0;
for(int j=0;j<len;j++){//像分析中一样求l[i],r[i]
if(str[j]=='(') cnt++;
else cnt--;
l[i]=min(l[i],cnt);
}
r[i]=cnt;
table[r[i]+addv].push_back(l[i]);//hash,为了防止负数人为加上addv,addv就相当于新的零点
}
for(int i=1;i<maxn;i++) if(table[i].size()!=0) sort(table[i].begin(),table[i].end());//排序,为了二分查找
long long ans=0;
for(int i=1;i<=n;i++){
if(l[i]>=0){
int tmp=addv-r[i];//即-r[i]
ans+=table[tmp].end()-lower_bound(table[tmp].begin(),table[tmp].end(),-r[i]);//lower_bound返回第一个>=x的位置,用结尾去-它,可求出l[j]=r[j]=-r[i]的j的个数
}
}
printf("%I64d\n",ans);
}
Codeforces 990C (模拟+组合数学)的更多相关文章
- CodeForces - 427B (模拟题)
Prison Transfer Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Sub ...
- CodeForces - 404B(模拟题)
Marathon Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Submit Sta ...
- Codeforces 709B 模拟
B. Checkpoints time limit per test:1 second memory limit per test:256 megabytes input:standard input ...
- CodeForces - 404A(模拟题)
Valera and X Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Submit ...
- Codeforces 390A( 模拟题)
Inna and Alarm Clock Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64 ...
- Codeforces 452D [模拟][贪心]
题意: 给你k件衣服处理,告诉你洗衣机烘干机折叠机的数量,和它们处理一件衣服的时间,要求一件衣服在洗完之后必须立刻烘干,烘干之后必须立刻折叠,问所需的最小时间. 思路: 1.按照时间模拟 2.若洗完的 ...
- CodeForces - 796B 模拟
思路:模拟移动即可,如果球落入洞中停止移动.注意:有可能第一个位置就是洞!! AC代码 #include <cstdio> #include <cmath> #include ...
- Colorful Bricks CodeForces - 1081C ( 组合数学 或 DP )
On his free time, Chouti likes doing some housework. He has got one new task, paint some bricks in t ...
- CodeForces - 864C-Bus-(模拟加油站问题)
https://vjudge.net/problem/CodeForces-864C 题意:两地之间有个加油站,往返走k个单程,最少加油多少次. 大佬几十行代码就解决,我却要用一百多行的if语句模拟解 ...
随机推荐
- PageOffice修改注册码升级版本
java: 删除pageoffice.jar所在目录(一般是WEB-INF/lib)下的license.lic文件(若服务器运行时找不到该文件,可在浏览器地址栏里面通过localhost方式访问pos ...
- CSS3——制作带动画效果的小图片
下了一个软件:ScreenToGif用来截取动态图片,终于可以展示我的小动图啦,嘻嘻,敲开心! main.html <!DOCTYPE html> <html lang=" ...
- 下载csv
export function downloadCsv(val, key, name, keyName) { if (val.length) { let str = [] str.push(keyNa ...
- CSS3制作太极图以及用JS实现旋转太极图
太极图可以理解为一个一半黑一半白的半圆,上面放置着两个圆形,一个黑色边框白色芯,一个白色边框黑色芯. 1.实现黑白各半的圆形. .box{ width:200px;height:200px; bor ...
- django model 操作总结
使用场景 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了).//两个表的数据一一对应 例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足 ...
- SpringCloud 教程 (七)服务注册(consul)
一.consul 简介 consul 具有以下性质: 服务发现:consul通过http 方式注册服务,并且服务与服务之间相互感应. 服务健康监测 key/value 存储 多数据中心 consul可 ...
- 关于VS连接Oracle数据库提示:“尝试加载oracle客户端时引发badimage,如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题”的解决方案。
错误一.关于VS连接Oracle数据库提示:“尝试加载oracle客户端时引发badimage,如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题”的解决方案. ...
- Linux shell - 重命名文件和文件夹(mv)
linux下重命名文件或文件夹的命令mv既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录移动到/b下,并重命名为c mv /a /b/c
- 在Ubuntu18.04下安装Java 11
一直以来,本人都使用第三方软件包"ppa:linuxuprising/java"安装Java JDK,最近一次安装时发现无法成功.这是由于现在无法直接从Oracle官网下载Java ...
- win10 安装了virtualBox 启动报错 rc=-5640
刚刚安装的virtualbox 启动就弹窗报错,,但是通过找到log 发现了下面这样的一处报错: 然后搜素发现是跟win10应用程序错误,,解决办法如下: 1.到控制面板,,--程序 再次尝试,vir ...