2018湖南多校第五场-20180506 训练日志
Posted dowhile0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018湖南多校第五场-20180506 训练日志相关的知识,希望对你有一定的参考价值。
solved 5 (a b d f g)
rank 5/28
总体发挥较佳,虽然中期卡在了D,最后成绩还是完成了flag。dzcjj太强辣。
最直观的感受就是觉得时间不够用,这比之前做完水题就挂机的水平还是有很强的提高的。
A Bit String Reordering(暴搜)
B Miscalculation(模拟)
<qj>
本场最水的一道题,完全码力题。
题意:给一个字符串,里面包含了一些数学运算的式子,求两种定义下的值。(只存在加法和乘法)
第一种定义:先乘除后加减。
第二种定义:从左至右运算。
解法:模拟一下便可。(第一种可以用到stack来解决,第二种可以直接搞,当然也可以用queue)
D Space Golf(推物理公式)
F There is No Alternative(最小生成树相关)
G Flipping Parentheses (线段树 + 二分)
<qj>
题意:
给一个初始的字符串,由左括号和右括号组成,保证初始字符串平衡。
q个查询,翻转第pos个括号,问你翻转哪一个最靠左的括号能够使序列重新平衡。
每次操作会影响到后面的操作。
思路:
遇到括号平衡的问题,我们一般会想到前缀和表达,但这个题里存在翻转(修改)的操作,那么不难想到,能够实现前缀和 + 修改 的数据结构有线段树或树状数组。
由于性质,最后一个括号一定是 ‘)’ ,且prefix(最后一个)值为0, 才会平衡。
1.
如果翻转了一个 ‘)‘,那么从pos开始到结尾的前缀和应该都 +2 ,我们可以用线段树把这个区间的值都 +2 。
已知串要平衡,最后一个位置前缀和应该是 0 ,而目前最后一个位置是 2。
那么我们需要找到一个pos2,pos2翻转,使得[pos2,n]区间 -2。
然后这里为了不破坏平衡,区间内所有值都必须大于等于2。所以线段树可以去维护一个区间最小值,若区间最小值不小于2,该区间满足条件。
怎么找到最左的pos呢,我们可以用到二分搜索。
int l = 0, r = n+1;int mid = l+r>>1;
如果mid往右的所有前缀和满足条件,那么我们往左找[l,mid],否则往右找[mid,n]。
复杂度 O(Q*logN*logN)
2.
如果翻转了‘(’ , 跟上面是类似的。最后一个位置的前缀和应该是 -2。
如何找到最左的一个括号翻转,并使得最后一个位置前缀和变成0呢?
翻转从左开始第一个‘)’便可。
若前面全是‘(‘不难知道,在第pos个位置,prefix(pos)==pos,说明前面没有出现过‘)‘ 。
同上,二分去找第一个prefix(pos)!=pos的位置就可以了。
复杂度 O(Q*logN*logN)
上代码:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define maxn 300055 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define intmid int mid = (l+r)>>1 int n,q; char s[maxn]; int pre[maxn]; int cur[maxn<<2],minv[maxn<<2]; void push_up(int rt){ minv[rt] = min(minv[rt<<1] , minv[rt<<1|1]); } void push_down(int l,int r,int rt){ if(cur[rt]){ intmid; cur[rt<<1] += cur[rt]; cur[rt<<1|1]+= cur[rt]; minv[rt<<1] += cur[rt]; minv[rt<<1|1]+= cur[rt]; cur[rt]=0; } } void build(int l,int r,int rt){ intmid; cur[rt]=0; if(l==r){ minv[rt]=pre[l]; return ; } push_down(l,r,rt); build(lson);build(rson); push_up(rt); } void update(int ll,int rr,int val,int l,int r,int rt){ intmid; if( ll<=l && rr>=r ){ cur[rt]+=val; minv[rt]+=val; return ; } push_down(l,r,rt); if(ll<=mid)update(ll,rr,val,lson); if(rr>mid)update(ll,rr,val,rson); push_up(rt); } int querymin(int ll,int rr,int l,int r,int rt){ int ret=0x3f3f3f3f; if(ll<=l && rr>=r){ return minv[rt]; } push_down(l,r,rt); intmid; if(ll<=mid) ret = min(ret,querymin(ll,rr,lson)); if(rr>mid) ret = min(ret,querymin(ll,rr,rson)); return ret; } bool check(int pos){ int v = querymin(pos,n,1,n,1); if(v<2)return 1; return 0; } bool check2(int pos){ int v = querymin(pos,pos,1,n,1); if(v==pos)return 1; return 0; } int main(){ while(scanf("%d%d",&n,&q)!=EOF){ scanf("%s",s+1); for(int i=1;i<=n;i++){ pre[i]=pre[i-1]; if(s[i]==‘(‘)pre[i]++; else pre[i]--; } build(1,n,1); while(q--){ int pos; scanf("%d",&pos); if(s[pos]==‘(‘){ s[pos]=‘)‘; update(pos,n,-2,1,n,1); int l=0,r=n+1; while(l<r-1){ intmid; if(check2(mid)){ l=mid; } else r=mid; } printf("%d\n",r); s[r]=‘(‘; update(r,n,2,1,n,1); } else{ s[pos]=‘(‘; update(pos,n,2,1,n,1); int l=0,r=n+1; while(l<r-1){ intmid; if(check(mid)){ l=mid; } else r=mid; } printf("%d\n",r); s[r]=‘)‘; update(r,n,-2,1,n,1); } } } return 0; }
以上是关于2018湖南多校第五场-20180506 训练日志的主要内容,如果未能解决你的问题,请参考以下文章
杭电2018多校第五场(2018 Multi-University Training Contest 5) 1007.Glad You Came (HDU6356)-区间更新-线段树+剪枝
[2019杭电多校第五场][hdu6624]fraction