题面

[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 思维相关推荐

  1. 平衡线共模抑制原理和距离

    一句话概括: 双(或4)平衡线的物理式设计(共模抑制).差分信号的数字式抑制噪声的原理都是统一的,大多数的外在干扰都对相似(相同距离.相同阻抗等)的信号产生同样的干扰影响:-- 平衡线传输靠末端的共模 ...

  2. CF-477C(Dreamoon and Strings) DP

    CF-477C(Dreamoon and Strings) 题目链接 题意 两个串S,TS,TS,T,问SSS中删除[1,∣S∣][1,|S|][1,∣S∣]个字符之后,最多有多少个不重叠的T串 思路 ...

  3. 2021牛客多校5 - Double Strings(dp+组合数学)

    题目链接:点击查看 题目大意:给出两个字符串 sss 和 ttt,要求 "一段相同的前缀" + "一个不同的字符(满足s[i]<t[j])"+ " ...

  4. mit oracle 350平衡线,MIT MI-350 CVT 平衡线_已售器材欣赏区_信谊音响_二手音响_音响发烧站_高级音响 - 音响贵族网...

    美国MIT发烧线已有近20年的历史,人们对其最深的印象是它每条线身上都有的那个金属盒.这个盒子是MIT令音乐重放完美的"灵魂"所在,它包含了MIT独家的线路.电阻.电容等元件,使不 ...

  5. [XSY] 线图(树形DP、分类讨论)

    线图 如图,每个L(L(T))上的点对应T上的一条三点链 在连接L(L(T))上两点,当且仅当两点代表的三点链在T上有共边,且边权为 共边边权*2+非共边1边权+非共边2边权 在L(L(T))上从点u ...

  6. CodeForces - 336D Vasily the Bear and Beautiful Strings(dp+组合数学)

    题目链接:点击查看 题目大意:给出一个 01 字符串,规定求值的过程如下: 每次选择末尾的两个数字: 如果为 0 0 ,那么替换成一个 1 否则替换成一个 0 循环往复,直至只剩一个数字位置,剩下的数 ...

  7. [USACO07JAN]平衡的阵容Balanced Lineup BZOJ 1699

    题目背景 题目描述: 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连 ...

  8. 【HDU - 4055】Number String(dp,思维)

    题干: The signature of a permutation is a string that is computed as follows: for each pair of consecu ...

  9. Codeforces 1408 D. Searchlights(优化DP、思维)

    整理的算法模板合集: ACM模板 传送门 DP的思想,因为题目中有两个维度,数据达到了1e6,所以我们直接开二维数组显然不太恰当,而且我们的答案不好选取,我们可以使用一个技巧,开一维数组,用DP的下标 ...

  10. codeforces 808 E. Selling Souvenirs (dp+二分+思维)

    题目链接:http://codeforces.com/contest/808/problem/E 题意:最多有100000个物品最大能放下300000的背包,每个物品都有权值和重量,为能够带的最大权值 ...

最新文章

  1. Linux搭建Node.js环境
  2. react+redux+generation-modation脚手架搭建一个todolist
  3. Spring之AOP实现
  4. Java中堆内存和栈内存详解(转)
  5. 科学数字_Excel分列时拒绝让超过15位的数字变成科学计数法
  6. 做本地杂志如何赚钱?
  7. 单链表的顺序查找c语言,单链表(C语言)
  8. UNIX文件系统结构
  9. 【毕业设计】2021年计算机专业-12套精品项目源码免费下载
  10. 京瓷打印机p5026cdn_京瓷p5026cdn打印机驱动
  11. JAVA解析RTF 文件
  12. MySQL登录命令详解
  13. 如何将硬盘克隆到固态硬盘,固态硬盘系统克隆怎么弄
  14. 矩阵求导公式的推导和计算(公式推导法)
  15. 笔杆网试用---感官体验篇一
  16. Auto CAD标注表面粗糙度的方法
  17. 每日刷题记录 (二十)
  18. 如何自动生成论文目录
  19. 云服务器安装SSL证书,实现https访问
  20. 读书笔记《不拘一格》

热门文章

  1. 网站banner图片制作(简易版)
  2. 调用新浪微博显示用户信息
  3. 压力测试 Monkey 应用程序无响应ANR Application No Response(转)
  4. 使用下面的方法有利于提高JS代码的执行效率
  5. java中输入输出总结
  6. Wise UNpacker 0.91A [with Delphi Source]
  7. samba 和 nfs 实验
  8. linux上调用短信接口,短信猫接口程序Gnokii For Linux安装
  9. linux主从库配置文件,Linux系统中MongoDB安装及主从配置linux操作系统 -电脑资料
  10. python的最受欢迎的库_年度十大最受欢迎机器学习Python库