[USACO12NOV]同时平衡线Concurrently Balanced Strings DP map 思维
题面
[USACO12NOV]同时平衡线Concurrently Balanced Strings
题解
考虑DP。
\(f[i]\)表示以\(i\)为左端点的合法区间个数。令\(pos[i]\)表示以\(i\)为左端点,最靠左的合法右端点。
那么有如下转移:
\(f[i] = f[pos[i] + 1] + 1\).
1表示[i, pos[i]]这段合法区间,\(f[pos[i] + 1]\)表示在这段合法区间的基础上,还可以在后面拼接更多合法区间。
那么我们的目的就是求\(pos[i]\).
考虑一段区间为什么合法?
我们令左括号为1,右括号为-1,然后对于每一行单独求前缀和。
那么对于每行单独考虑,一个区间\([l, r]\)需要满足2个限制:
- \(sum[r] - sum[l - 1] = 0\)
- 区间内任意一点\(i\)满足\(sum[i] - sum[l - 1] >= 0\)
考虑分开处理这2个限制。
对于每个左端点\(i\),处理出使得区间前缀为负的第一个点,那么只要右端点不超过这个点,就满足第二点限制。
对于同一列的每一行都求出这个值,然后取min,得到值\(t\),表示第\(i\)列的右端点只要不超过\(t\)就可以对于\(k\)行都满足第二点限制。
令这个最小的,令左端点\(i\)不满足第二点限制的右端点为\(lim[i]\)
然后从大到小枚举列\(i\),那么我们要处理的就是第一点限制。
只需要查询最近的一个右端点满足当前列的\(k\)行与第\(i - 1\)列的\(k\)行相同即可,
如果这个最近的右端点都大于等于\(lim[i]\),那么对于这个左端点就没有合法方案了。
否则我们就找到了\(pos[i]\).
那么这两个东西应该如何求呢?
求\(lim[i]\):
先对每一行求出对应的右端点,然后取\(min\)即可,接下来讲如何对于每行求这个右端点。
如果有右端点满足使得以\(i\)为左端点的区间前缀和为负,那么肯定会有一个右端点最先满足这个东西,也就是\(sum[j] - sum[i - 1] = -1\).那么我们查询满足\(sum[j] = sum[i - 1] - 1\)的最小值即可。
这个我们从大到小枚举\(i\),用\(minn[i]\)表示到当前为止,值为\(i\)的点的最小下标是多少,然后就可以直接得到了。
求\(pos[i]\):
用和上面类似的方法,只不过我们这次是要找一个使得\(k\)元组相等的最小\(j\)。
因为\(k\)很小,所以可以把\(k\)个值都存到\(map\)里暴力找。
当然也有更优美一点的做法,对这\(k\)个数进行\(hash\)然后再丢\(map\)里面找,这样\(map\)就只用存1个数了。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define LL long long
#define AC 12
#define ac 100100
#define inf 2139062143
#define base 13
#define us signed
#define bu 16777215
#define h(x) (x & bu)
#define g(x) (x + 50000)int n, m;
LL ans, f[ac];
int lim[ac], minn[ac];
int Head[AC], date[ac], Next[ac], tot;
char s[ac];
map <us LL, int> M;
struct node{int s[AC]; us LL opt;friend bool operator == (node a, node b){for(R i = 1; i <= m; i ++) if(a.s[i] != b.s[i]) return false;return true;}
}sum[ac];inline void upmax(int &a, int b) {if(b > a) a = b;}
inline void upmin(int &a, int b) {if(b < a) a = b;}inline int read()
{int x = 0;char c = getchar();while(c > '9' || c < '0') c = getchar();while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x;
}/*void ins(int w)//插入sum[w]
{int f = h(sum[w].opt);bool done = false;for(R i = Head[f]; i; i = Next[i]){int now = date[i];if(sum[now] == sum[w]) upmin(date[i], w);//保留更小的下标}if(!done) Head[++ tot] = w, Next[tot] = Head[f], Head[f] = tot;
}int find(int w)//找到值与sum[w]相同的,最小的x
{int go = h(sum[w].opt);for(R i = Head[go]; i; i = Next[i]){int now = date[i];if(sum[now] == sum[w]) return now;}return inf;
}*/void pre()
{m = read(), n = read();for(R i = 1; i <= m; i ++){scanf("%s", s + 1);for(R j = 1; j <= n; j ++) sum[j].s[i] = sum[j - 1].s[i] + ((s[j] == ')') ? -1 : 1);}
}void build()
{for(R i = 1; i <= n; i ++) lim[i] = inf;for(R i = 1; i <= m; i ++){memset(minn, 127, sizeof(minn));for(R j = n; j; j --)//对于每行的每个点找右边的,最近的,区间和为-1的点(比当前前缀小1{upmin(minn[g(sum[j].s[i])], j);//先加入,防止第一个括号是右括号upmin(lim[j], minn[g(sum[j - 1].s[i] - 1)]);//判断[l, r] = 0,需要用到sum[l - 1]和sum[r]}}for(R i = 1; i <= n; i ++)for(R j = 1; j <= m; j ++)sum[i].opt = sum[i].opt * base + sum[i].s[j];
}void work()
{for(R i = n; i; i --){int pos = M[sum[i - 1].opt];//找最小的和当前l - 1前缀相同的前缀if(pos && pos < lim[i]) f[i] = f[pos + 1] + 1, ans += f[i];if(M[sum[i].opt]) upmin(M[sum[i].opt], i);else M[sum[i].opt] = i;}printf("%lld\n", ans);
}int main()
{
// freopen("in.in", "r", stdin);pre();build();work();
// fclose(stdin);return 0;
}
转载于:https://www.cnblogs.com/ww3113306/p/10487114.html
[USACO12NOV]同时平衡线Concurrently Balanced Strings DP map 思维相关推荐
- 平衡线共模抑制原理和距离
一句话概括: 双(或4)平衡线的物理式设计(共模抑制).差分信号的数字式抑制噪声的原理都是统一的,大多数的外在干扰都对相似(相同距离.相同阻抗等)的信号产生同样的干扰影响:-- 平衡线传输靠末端的共模 ...
- CF-477C(Dreamoon and Strings) DP
CF-477C(Dreamoon and Strings) 题目链接 题意 两个串S,TS,TS,T,问SSS中删除[1,∣S∣][1,|S|][1,∣S∣]个字符之后,最多有多少个不重叠的T串 思路 ...
- 2021牛客多校5 - Double Strings(dp+组合数学)
题目链接:点击查看 题目大意:给出两个字符串 sss 和 ttt,要求 "一段相同的前缀" + "一个不同的字符(满足s[i]<t[j])"+ " ...
- mit oracle 350平衡线,MIT MI-350 CVT 平衡线_已售器材欣赏区_信谊音响_二手音响_音响发烧站_高级音响 - 音响贵族网...
美国MIT发烧线已有近20年的历史,人们对其最深的印象是它每条线身上都有的那个金属盒.这个盒子是MIT令音乐重放完美的"灵魂"所在,它包含了MIT独家的线路.电阻.电容等元件,使不 ...
- [XSY] 线图(树形DP、分类讨论)
线图 如图,每个L(L(T))上的点对应T上的一条三点链 在连接L(L(T))上两点,当且仅当两点代表的三点链在T上有共边,且边权为 共边边权*2+非共边1边权+非共边2边权 在L(L(T))上从点u ...
- CodeForces - 336D Vasily the Bear and Beautiful Strings(dp+组合数学)
题目链接:点击查看 题目大意:给出一个 01 字符串,规定求值的过程如下: 每次选择末尾的两个数字: 如果为 0 0 ,那么替换成一个 1 否则替换成一个 0 循环往复,直至只剩一个数字位置,剩下的数 ...
- [USACO07JAN]平衡的阵容Balanced Lineup BZOJ 1699
题目背景 题目描述: 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连 ...
- 【HDU - 4055】Number String(dp,思维)
题干: The signature of a permutation is a string that is computed as follows: for each pair of consecu ...
- Codeforces 1408 D. Searchlights(优化DP、思维)
整理的算法模板合集: ACM模板 传送门 DP的思想,因为题目中有两个维度,数据达到了1e6,所以我们直接开二维数组显然不太恰当,而且我们的答案不好选取,我们可以使用一个技巧,开一维数组,用DP的下标 ...
- codeforces 808 E. Selling Souvenirs (dp+二分+思维)
题目链接:http://codeforces.com/contest/808/problem/E 题意:最多有100000个物品最大能放下300000的背包,每个物品都有权值和重量,为能够带的最大权值 ...
最新文章
- Linux搭建Node.js环境
- react+redux+generation-modation脚手架搭建一个todolist
- Spring之AOP实现
- Java中堆内存和栈内存详解(转)
- 科学数字_Excel分列时拒绝让超过15位的数字变成科学计数法
- 做本地杂志如何赚钱?
- 单链表的顺序查找c语言,单链表(C语言)
- UNIX文件系统结构
- 【毕业设计】2021年计算机专业-12套精品项目源码免费下载
- 京瓷打印机p5026cdn_京瓷p5026cdn打印机驱动
- JAVA解析RTF 文件
- MySQL登录命令详解
- 如何将硬盘克隆到固态硬盘,固态硬盘系统克隆怎么弄
- 矩阵求导公式的推导和计算(公式推导法)
- 笔杆网试用---感官体验篇一
- Auto CAD标注表面粗糙度的方法
- 每日刷题记录 (二十)
- 如何自动生成论文目录
- 云服务器安装SSL证书,实现https访问
- 读书笔记《不拘一格》
热门文章
- 网站banner图片制作(简易版)
- 调用新浪微博显示用户信息
- 压力测试 Monkey 应用程序无响应ANR Application No Response(转)
- 使用下面的方法有利于提高JS代码的执行效率
- java中输入输出总结
- Wise UNpacker 0.91A [with Delphi Source]
- samba 和 nfs 实验
- linux上调用短信接口,短信猫接口程序Gnokii For Linux安装
- linux主从库配置文件,Linux系统中MongoDB安装及主从配置linux操作系统 -电脑资料
- python的最受欢迎的库_年度十大最受欢迎机器学习Python库