模拟赛的一个题和反思

反思

今天的模拟赛大翻车了。。
本来是320的,但最后FST剩了200
实在不该
反思一下原因是什么
分数组成50+30+100+20
首先,前两题应该是A的
但是T1,对自己的复杂度过于自信,最终T炸了
对于签到题,应该还是要做到不失误
对于比较简单的题,如果感觉复杂度上了 107 10 7 ,然后就要考虑一下常数问题,否则很容易T,更何况这题有5组数据
所以理应花更多的时间来思考,而不是觉得能过就行
如果在省选里面签到题炸了,那就很难取得成绩了
然后第二题的话,做得比较失败
一开始想的状态无法矩乘是比较尴尬的
然后推了一下就去找规律了。。其实想多一会,把状态改一点点就可以容易矩乘了。。
虽然最后用规律搞出了一个不一样的递推式
但是确由于矩乘没有改过来而GG了。。
由于第一次打的矩乘是没有负数的,后面的那一个有
于是模没有转正。。
这个是十分不应该的
然后这一次的话,因为测了多组数组而没有写对拍,也是不该
因为暴力DP都写出来了,写多一个maker也不用浪费多少时间
但是却可以挽回70分,在省选中,还是应该保证写了对拍的情况下再去开第三题
因为第二题也是一个很好拿分的题,也是必须要拿到的
然后由于第二题的缘故,第四题没有时间想
于是想了部分分,虽然没打完,但拿了最暴力的一部分,也不算是亏吧

我觉得这一次低分的主要原因在于A,B题,而不是C,D题的缘故

一个题

就是每一个括号序列
两两配对
问你把某一段拿出来,问你这一段括号配对完后,剩下的第k个在原串中的位置
带修改

题解

考试的时候没有细想,想了部分分
但是由于想得不够久,不是特别好写
但我觉得这个决策也不是特别亏吧

这里写图片描述

一开始想的是直接维护答案,后来才想到分开查1和查0会好写很多。。
然后二分显然是可以在线段树上完成的

然后就没有了

不想写了。。给个std吧。。

#include<cstdio>
#include<cstring>
#define lc (o<<1)
#define rc (lc^1)
#define mid ((l+r)>>1)
using namespace std;
int t,n,m,x,y,k,L,R;
struct xd_tree{int L,R;} a[2100100];
int read() {
    int tmp=0,fh=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') fh=-1; c=getchar();}
    while (c>='0'&&c<='9') tmp=tmp*10+c-48,c=getchar();
    return tmp*fh;
}
void update(int o) {
    a[o].L=a[lc].L; a[o].R=a[rc].R;
    if (a[lc].R<a[rc].L) a[o].L+=a[rc].L-a[lc].R;
    else a[o].R+=a[lc].R-a[rc].L;
}
void build(int o,int l,int r) 
{
    if (l<r) 
    {
        build(lc,l,mid); build(rc,mid+1,r);
        update(o);
    } 
    else 
    {
        char c=getchar(); while (c!='0'&&c!='1') c=getchar();
        if (c=='1') a[o].L=1, a[o].R=0;
        else a[o].L=0, a[o].R=1;
    }
}
void change(int o,int l,int r,int pos) {
    if (l==r) {
        a[o].L^=1; a[o].R^=1; return;
    }
    if (pos<=mid) change(lc,l,mid,pos);
    else change(rc,mid+1,r,pos);
    update(o);
}
void query(int o,int l,int r,int lt,int rt) {
    if (lt<=l&&r<=rt) {
        if (R<a[o].L) L+=a[o].L-R, R=a[o].R;
        else R+=a[o].R-a[o].L;
        return;
    }
    if (lt<=mid) query(lc,l,mid,lt,rt);
    if (rt>mid) query(rc,mid+1,r,lt,rt);
}
int find_r(int o,int l,int r,int pos,int k) {
    //printf("fr %d %d %d %d %d %d %d\n",o,l,r,a[o].L,a[o].R,pos,k);
    if (l==r&&a[o].L==1&&k==1) return l;
    if (l==pos&&k>a[o].L) return r+k-a[o].L+a[o].R;
    if (pos>mid) return find_r(rc,mid+1,r,pos,k);
    int tmp=find_r(lc,l,mid,pos,k);
    if (tmp<=mid) return tmp;
    return find_r(rc,mid+1,r,mid+1,tmp-mid);
}
int find_l(int o,int l,int r,int pos,int k) {
    //printf("fl %d %d %d %d %d %d %d\n",o,l,r,a[o].L,a[o].R,pos,k);
    if (l==r&&a[o].R==1&&k==1) return r;
    if (r==pos&&k>a[o].R) return l-k+a[o].R-a[o].L;
    if (pos<=mid) return find_l(lc,l,mid,pos,k);
    int tmp=find_l(rc,mid+1,r,pos,k);
    if (tmp>mid) return tmp;
    return find_l(lc,l,mid,mid,mid-tmp+1);
}
int main() {
    freopen("grancrevasse.in","r",stdin);
    freopen("grancrevasse.out","w",stdout);
    memset(a,0,sizeof(a));
    n=read(); m=read(); build(1,1,n);
    while (m--) {
        if (read()==1) change(1,1,n,read());
        else {
            x=read(); y=read(); k=read();
            L=R=0; query(1,1,n,x,y);
            //printf("%d %d\n",L,R);
            if (k>L+R) printf("-1\n");
            else if (k<=L) printf("%d\n",find_r(1,1,n,x,k));
            else printf("%d\n",find_l(1,1,n,y,L+R-k+1));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值