博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
topcoder srm 688 div1 -3
阅读量:6581 次
发布时间:2019-06-24

本文共 3114 字,大约阅读时间需要 10 分钟。

1、给出一个只包含'(',')'的字符串$s$,现在对它进行若干次如下操作使其变成匹配的括号串(每次操作包含3个步骤):(1)选择 $L,R,L\leq R$;(2)将$L,R$之间的字符翻转;(3)将$L,R$之间所有的'('改成')',所有的')' 改成'('。

思路:首先去掉原串中已经配对的括号,那么剩下的括号序列是以下情况:(1)空串;(2)))));(3)((((;(4)))))((。第一种情况不需要处理。对于第三种情况和第四种情况,都可以将其变成第二种情况。第二种情况只需要对前一半做操作即可。另外,每次操作的时候不会影响已经删掉的匹配的串。

#include 
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N=100005;void deal(string &s,int L,int R){ reverse(s.begin()+L,s.begin()+R+1); for(int i=L;i<=R;++i) { if(s[i]=='(') s[i]=')'; else s[i]='('; }}vector
cal(string S){ deque
st; for(int i=0;i<(int)S.size();++i) { if(S[i]=='(') st.push_back(i); else if(!st.empty()&&S[st.back()]=='(') st.pop_back(); else st.push_back(i); } if(st.empty()) return vector
{}; vector
ans; for(int i=0;i<(int)st.size();++i) { if(S[st[i]]=='(') { int L=st[i]; int R=st.back(); ans.push_back(L); ans.push_back(R); deal(S,L,R); vector
tmp=cal(S); for(int i=0;i<(int)tmp.size();++i) ans.push_back(tmp[i]); return ans; } } ans.push_back(st.front()); ans.push_back(*(st.begin()+st.size()/2-1)); return ans;}class ParenthesesDiv1Easy{public: vector
correct(string s) { if((s.size())&1) return vector
{-1}; return cal(s); }};

2、给出一个只包含'(',')'的字符串$s$。对它做一些操作之后使得$L_{i},R_{i}$之间的串是匹配的括号串。每次操作选择两个位置$i,j$然后交换这两个位置的字符。给出最少的操作数。

思路:

(1)首先,如果$[x,y_{1}],[x,y_{2}],y_{1}< y_{2}$都要是匹配的,那么有$[x,y_{1}],[y_{1}+1,y_{2}]$之间要分别匹配。

(2)其次,如果$[x_{1},y_{1}],[x_{2},y_{2}]$都要匹配,$x_{1}<x_{2}<y_{1}<y_{2}$,那么$[x_{1},x_{2}-1],[x_{2},y_{1}],[y_{1}+1,y_{2}]都要匹配$

经过这样的处理,最后所有匹配的区间可能会有包含的关系,然后没有其他相交关系。所以可以按照区间长度排序,一个区间一个区间进行处理。每个区间都相等于一个小的串(对于包含小区间的大区间不需要考虑已经处理的小区间,只需要考虑除了小区间外其他的部分匹配)。对于一个串$T$,定义$f(T)$表示将$T$变成匹配最少的修改数,这个修改指的是单独把左括号改成右括号或右括号改成左括号的次数,而不是交换。最后的答案其实是重复了一半,除以2即可。还有一个问题是有可能所有考虑的范围内的左括号数过于多,以至于在未考虑区间根本没有足够的右括号可以交换,这种情况是无解的。

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N=2005;int n,m,f[N][N];int a[N],b[N];int cmp(pair
a,pair
b){ int ll=a.second-a.first; int rr=b.second-b.first; if(ll!=rr) return ll
y) x=y;}int cal(string s){ if(s.size()&1) return -1; const int L=1; const int R=(int)s.size(); for(int i=L-1;i<=R;++i) memset(f[i],-1,sizeof(f[i])); f[L-1][0]=0; for(int i=L;i<=R;++i) { if(s[i-1]=='(') ++tot0; else ++tot1; int w; if(s[i-1]==')') w=1; else w=0; for(int j=1;j<=n;++j) if(f[i-1][j-1]!=-1) up(f[i][j],f[i-1][j-1]+w); if(s[i-1]==')') w=0; else w=1; for(int j=0;j
>1; return f[R][0];}vector
RR[N];vector
> req;class ParenthesesDiv1Medium{public: int minSwaps(string s,vector
L,vector
R) { n=(int)s.size(); m=(int)L.size(); for(int i=1;i<=n;++i) { if(s[i-1]=='(') a[i]=0; else a[i]=1; } for(int i=0;i
i;--j) if(RR[j].size()&&RR[j].back()>=RR[i][0]) x=min(x,j-1); if(x
totlen) ans+=tot0-totlen; else ans+=abs(totlen-tot1); for(int i=1;i<=n;++i) if(!b[i]) { if(a[i]) --tot0; else --tot1; } if(tot0>totlen||tot1>totlen) return -1; return ans>>1; }};

  

转载地址:http://kenno.baihongyu.com/

你可能感兴趣的文章
Android Service基本知识总结(一)
查看>>
LeetCode OJ:Merge Intervals(合并区间)
查看>>
【Gamma】Scrum Meeting 7
查看>>
马云:假如十年前就有博士,今天阿里的技术会很不一样
查看>>
.net 简单图表控件 (介绍测试示例使用部分) [b/s应用程序控件] I
查看>>
win7下VMware安装提示错误1923 or 1920、VMware USB Arbitration Service无法启动、VMware-无法打开内核设备解决办法...
查看>>
C. Karen and Game
查看>>
Lua中的捕获
查看>>
【C++11】新特性——auto的使用
查看>>
高精度加法模板
查看>>
* spring mvc
查看>>
BI项目历程
查看>>
《MySQL入门很简单》练习6.5
查看>>
【Android 进阶】临时卸载root和恢复root功能
查看>>
166. Fraction to Recurring Decimal
查看>>
【转载】浅谈C#委托和事件
查看>>
HDU 3074 Multiply game(线段树)
查看>>
Chapter 1. HTML---标签、表格
查看>>
Chapter 8. 面向对象(类库、委托)
查看>>
马哥 Linux文本处理和文件查找 笔记
查看>>