……这个在线测试赛后不可练习,题目也看不了了,但是代码我都好好的留下来了
先上提交记录:
之后从前往后复述题意,写题解吧。
本文地址:http://blog.csdn.net/fcxxzux/article/details/51931463
题意:给你2个长度相等的,由小写字母组成的字符串。现在允许你做一个操作:把2个字符串中出现的字符A换成字符B(允许自己换成自己,2个字符串里出现的字符A都要被替换),问有没有一种替换方案,使得替换后2个字符串完全一样?
比如,输入:
ababcd
babacd
输出Yes,因为可以通过把a换成b,使得2个字符串都变成bbbbcd。
——英文题面描述的题意有毒,当搞懂正确题意后,还是很白送的:暴力枚举所有替换方案,并检查
也就26*26*length,这里length还只有100,直接交。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
char sa[105],sb[105];
int len;
char change(char x,char s,char g){
return x==s?g:x;
}
bool check(char src,char goal){
for(int i=0;i
2个人Takahashi和Aoki站在起跑线上。已知:
1、发令枪响后,Takahashi立刻出发,Aoki将延迟0.5秒出发
2、已知Takahashi跑一圈用a秒,Aoki跑一圈用b秒(a和b都是整数)
求:第k次有人冲过起点线的时候,是谁冲过的?
比如a=3 b=2 k=1,输出Aoki,a=3 b=2 k=2,输出Takahashi
从起点出发不算冲过起点线,之后2.5秒的时候Aoki冲过起点线,3秒的时候Takahashi才冲过起点线,下一次是Aoki在4.5秒冲过,再之后是Takahashi在6秒冲过,之后Aoki在6.5和8.5秒各自冲过一次,9秒的时候Takahashi再冲过。
做法:因为k实在不大(k<=100000),所以,与其写二分搜索伤害自己,不如,模拟。
采用事件触发的思路,记录每个人下次冲过起点线的时间(timer被触发的时刻),之后循环判断谁冲过起点线,并更新他下次冲过起点线的时间。
注意由于a,b<=100000,导致时刻超过32位整型的表示范围,请使用64位整型。
#include
#include
#include
#include
#include
#include
#include
#include
#include
给你一个r*c的矩阵(r,c<=50),以左上角为(1,1),向下为x增大方向,向右为y增大方向,每个单元里是2种多米诺骨牌:
R:向右倒
C:向下倒
输入中还有一种情况
?:表示不确定,可以是R或C的任意一种(保证输入中不超过10个?)
现在你需要把所有多米诺骨牌推倒。请问,最少推倒次数的期望是多少?
比如,输入
1 2
??
输出1.5000000000000000000
对??,一共4种可能
RR、RC、CR、CC
对RR、RC,推倒全部骨牌,只需要动手1次(推(1,1))
对CR、CC,推倒全部骨牌,必须动手2次
所以,最小推倒次数的期望是1.5。
因为输入中不超过10个?,要枚举的情况也就1024种,所以暴力枚举走起。
对每种恢复的情况,怎么求最小的推倒次数期望呢?
因为骨牌只能向下和向右,不会回头,所以,我们只要找一块不会有任何骨牌可以压到的骨牌去推就行了
比如,上来就先推(1,1),因为(1,1)没有上面的和左边的骨牌了
之后再找一块没有上面和左边的骨牌的去推,贪心推完,就是最少次数。
(代码实现中采用了从第1行扫到最后一行,每行从左向右扫,没倒就推的办法。想一想,为什么这样找到的骨牌一定满足条件?)
最后使用数学期望的定义,算一下,输出,完事。
#include
#include
#include
#include
#include
#include
#include
#include
现在你有一个长度为n(n<=300000)的,残缺的括号序列(只由' ( ' 和 ' ) '组成),你需要通过插入字符,使得这个残缺的序列变成合法的括号序列
你可以在原始残缺序列的开始、末尾和任意2个字符之间加 ' ( ' 或者 ' ) ' ,一个位置可以插入多次,每个位置有不同的代价。
求变成合法的括号序列需要的最小代价。
比如:输入
4
)(()
1 7 2 8 5
输出:3
在最开头和两个(中间分别插入(和),得到:
( ) ( ) ( )
(加粗的字符为插入的字符)
插入代价为1+2=3,这是最小的方案。
下面留白,这个题有点意思,大家可以思考一下。
做法:
考虑如何进行括号匹配的检查。
从左到右,碰到左括号压栈,碰到右括号出栈
如果需要出栈的时候,栈里没有左括号,那就不是合法序列,直接返回false
如果整个串处理完了,栈里还有左括号,那也不是合法序列,返回false
现在要变成合法序列,就要考虑,这两种返回false的情况都应该避免。
先考虑解决第一种情况。
如果要出栈的时候没有左括号,那就——强行塞给他一个啊!
所以,从左到右,一个右括号找不到匹配的左括号的时候,在这个右括号前面的所有位置里,挑一个代价最小的位置,补上一个左括号。
(for dummies:挑一个代价最小的位置,这件事情怎么做才做的漂亮?
答:你看你现在要从左到右扫过去吧?那我可不可以同期维护一个变量,表示前面的东西的最小值?当我考虑的位置往后移的时候,最新的最小值=min(之前的最小值,新位置的值))
ok,现在考虑解决第二个问题——栈里残留的左括号。
考虑从右往左进行二次检查,
之前我们希望对每个要求出栈的 ) ,有残余的 ( 与之匹配
现在,我们希望对每个 ( ,要求有多余的 ) 与之匹配——而之前第一遍多出来的(是没有的
所以,类似的,从后往前扫描,) 入栈,( 出栈,出栈时没有对应括号的,在之前扫过的位置挑一个代价最小的地方补一个 ) 。
问题解决。
时间复杂度:正着扫一遍,倒着扫一遍,所以是O(n)的。
因为最坏情况下,一个位置的权值有10亿之大,最坏有300000括号要插入,所以,结果需要用64位整型表示。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
template
inline void scan(T &ret) {
char c; ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
inline void out(long long x) {
if(x>9) out(x/10);
putchar(x%10+'0');
}
ll ans=0;
char str[300005];
int weight[300005];
int main(){
int n;
scanf("%d%s",&n,str);
for(int i=0;i<=n;i++)scan(weight[i]);
{
int left=0;
int minv=weight[0];
for(int i=0;i=0;i--){
if(str[i]=='(')--left;
else if(str[i]==')')++left;
if(left<0){
ans+=minv;
left=0;
str[i]=' ';
}
minv=min(minv,weight[i]);
}
}
out(ans);
return 0;
}