zoukankan      html  css  js  c++  java
  • NOIP模拟测试16「Drink·blue·weed」

    话说这次考试

    Drink

    非常棒的一道卡常练习题,适合练习卡常

    真的很棒

    前置卡常知识

    1.char要比int快

    char是最快的

    输出putchar,输入getchar

    在这个题快了7000豪

    2.read

    快读非常棒,让你变得更快,fread更棒,fread会爆炸,考试时不要用fread

    3.循环展开

    循环展开非常棒,虽然看上去没什么用,然而循环展开会让你的程序快很多,循环展开往往是使你从T90到A的关键

    4.inline

    inline没什么用

    大多数时候都没有什么用,一般时间不会发生什么变化,然而在mex这个题inline突然变得有用

    突然变快.jpeg

    5.register

    大多数时候都没有什么用,然而有时会突然变快,有时还会变慢

    暂时没有例子,(或者说只有变慢的例子)

    6.STL

    priority_queue手打,

    stack手打

    map手打(不是让你打红黑树,是hash表)

    stack真的慢,stack打起来也好打,手打

    7.mod

    define或者const

    定义成变量会很慢,

    8.*2变<<1 /2 变>>1 ==变 ! ^

    上面的卡常应用到这个题呢

    char+循环展开

     代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll int
    #define A 2100
    char a[A][A];
    ll n,m,k;
    const int L=1<<20|1;
    char buffer[L],*S,*T;
    #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
    const int maxn=100000+5;
    inline int read(){
        register int ret;
        register char r;
        while(r=getchar(),r<'0'||r>'9');ret=r-48;
        while(r=getchar(),r>='0'&&r<='9')ret=ret*10+r-48;
        return ret;
    }
    int main(){
        n=read(),m=read(),k=read();
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=m;j++){
                register int ret;
                char r=getchar();
                while(!isdigit(r)) r=getchar();
                a[i][j]=r;
            }
        for(ll j=1,x,y,c,xl,yl;j<=k;j++){
            x=read(),y=read(),c=read();
            xl=x+c-1,yl=y+c-1;
            while(c>1){    
                for(ll i=0;i<=c-2;i++){
                    ll a1=a[xl-i][y],a2=a[x][y+i],a3=a[x+i][y+c-1],a4=a[x+c-1][yl-i];
                    a[x][y+i]=a1,a[x+i][yl]=a2,a[xl][yl-i]=a3,a[xl-i][y]=a4;
                }
                x++,y++,yl--,xl--,c-=2;
            }
        }
        for(ll i=1;i<=n;i++,puts(""))
            for(ll j=1;j<=m;j++){
                putchar(a[i][j]);putchar(' ');
            }
    }

    blue

    这个题它不卡set它卡splay!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    贪心,都说这个题很水,但我还是觉得不明白,看题解也是似懂非懂的

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define A 5010101
    #define Inf 10000000ll
    #define ll long long
    #define py printf("*****
    ")
    #define mem(a) memset(a,0,sizeof(a))
    ll landu[A],head[A],nx[A],ver[A],edg[A],dep[A],a[A],bl[A],blx[A],ch[A][2],cnt[A],size[A],key[A],fa[A];
    ll n,m,tot=1,S,T,t,D,L,sz,rt;
    set<ll> s;
    inline ll read(){
        ll f=1,x=0;char c=getchar();
        while(!isdigit(c)) {
            if(c=='-') f=-1;
            c=getchar();
        }
        while(isdigit(c)){
            x=(x<<1)+(x<<3)+c-'0';
            c=getchar();
        }
        return f*x;
    }
    inline void clear(ll x)
    {
        ch[x][0]=ch[x][1]=key[x]=cnt[x]=fa[x]=size[x]=0;
    }
    inline bool get(ll x)
    {
        return ch[fa[x]][1]==x;
    }
    inline void pushup(ll x)
    {
        if(x)
        {
            size[x]=cnt[x];
            if(ch[x][1]) size[x]+=size[ch[x][1]];
            if(ch[x][0]) size[x]+=size[ch[x][0]];
        }
    }
    inline void rotate(ll x)
    {
        ll old=fa[x],oldfa=fa[old],which=get(x);
        ch[old][which]=ch[x][which^1]; fa[ch[old][which]]=old;
        ch[x][which^1]=old; fa[old]=x;
        fa[x]=oldfa;
        if(oldfa) ch[oldfa][ch[oldfa][1]==old]=x;
        pushup(old);pushup(x); return ;
    }
    inline void splay(ll x)
    {
        for(ll f;f=fa[x];rotate(x))
            if(fa[f])
                rotate(get(f)==get(x)?f:x);
        rt=x;
    } 
    inline ll pre()
    {
        if(cnt[rt]>1) 
            return rt;
        ll now=ch[rt][0];
        while(ch[now][1]) now=ch[now][1];
        return now;
    }
    inline ll nxt()
    {    
        if(cnt[rt]>1)
            return rt;
        ll now=ch[rt][1];
            while(ch[now][0]) now=ch[now][0];
        return now;
    }
    inline void insert(ll x)
    {
        if(rt==0)
        {
            sz++;rt=sz;
            cnt[sz]=size[sz]=1;
            key[sz]=x;
            fa[sz]=ch[sz][0]=ch[sz][1]=0;
            return ;
        }
        ll f=0,now=rt;
        while(233)
        {    
            if(key[now]==x)
            {
                cnt[now]++;
                pushup(now);
                pushup(f);
                splay(now);
                return ;
            }
            f=now,now=ch[now][key[now]<x];
            if(now==0)
            {
                sz++;
                cnt[sz]=size[sz]=1;
                key[sz]=x;fa[sz]=f;
                ch[sz][1]=ch[sz][0]=0;
                ch[f][key[f]<x]=sz;
                pushup(f);splay(sz);return ;
            }
        }
    }
    inline ll rnk(ll x)
    {
        ll ans=1,now=rt;
        while(1)
        {
            if(x<key[now])
                now=ch[now][0];
            else
            {
                ans+=size[ch[now][0]];
                if(x==key[now])
                {
                    splay(now);return ans;
                }
                ans+=cnt[now];
                now=ch[now][1];
            }
        }
    }
    inline void del(ll x)
    {
        rnk(x);
        if(cnt[rt]>1)
        {cnt[rt]--;pushup(rt);return ;} 
        if(!ch[rt][0]&&!ch[rt][1])
        {clear(rt);rt=0;return ;}
        if(!ch[rt][0]||!ch[rt][1])
        {
            ll old=rt;
            rt=ch[rt][1]|ch[rt][0];
            clear(old);
            fa[rt]=0;
            return ;
        }
        ll older=rt; ll leftbigest=pre();
        splay(leftbigest);
        ch[rt][1]=ch[older][1];
        fa[ch[older][1]]=rt;
        clear(older);
        pushup(rt);
    }
    void re(){
        memset(ch,0,sizeof(ch));
        memset(size,0,sizeof(size));
        memset(key,0,sizeof(key));
        memset(fa,0,sizeof(fa));
    }
    int main()
    {
    set<ll>::iterator it;
        scanf("%lld",&t);
        while(t--){
            n=read(),m=read(),D=read(),L=read();
            s.clear();
            s.insert(-0x7ffffff);
            for(ll i=1;i<=n;i++){
                a[i]=read();
    //            insert(a[i]);
                s.insert(a[i]);
            }
            ll ok=1,cnt=0;
            while(ok){
                ll now=0;
                while(now<L){
                    if(now+D>=L) break;
    //                insert(now+D);
    //                ll x=pre();
    //                del(now+D);
                    ll x=*--s.upper_bound(now+D);
    //                printf("x=%lld  cnt=%lld
    ",x,cnt);
                    if(x<now){
                        ok=0;
                        break;
                    }
    //                now=key[x];
                    now=x;
                    s.erase(x);
    //                del(key[x]);
                }
                if(ok==0) break;
                cnt++;
                if(cnt==m) break;
            }
            if(cnt!=m)
                printf("%lld
    ",cnt);
            else
                printf("Excited
    ");
        }
    }

    weed

    比较神的一道题,学长讲的时候我没弄明白,这次考试30分就是报应

    以每个信息为下标记录三个信息,减少之后的层数,减少之后总的权值和,对之前区间减少的量

    首先在建树和修改时我们将叶子节点维护好,上传时利用这三个信息进行计算就行了

    优先删去右儿子节点(出现时间靠后),在右儿子不够时删除左儿子

    假设我们现在已经算完左右儿子

    那么如果右边儿子减少少于增加

    直接无脑加即可

        if(tr[rs].cut==0){
            tr[x].v=tr[ls].v+tr[rs].v;
            tr[x].c=tr[ls].c+tr[rs].c;
            tr[x].cut=tr[ls].cut+tr[rs].cut;
            return ;
        }

    如果右面儿子减少大于增加,并且右面儿子减少>=左面儿子层数和

    那么当前cut会有剩余,那么v直接赋c直接赋成右面儿子剩余v,c的值,

        if(tr[ls].c<=tr[rs].cut){
            tr[x].cut=tr[rs].cut-tr[ls].c+tr[ls].cut;
            tr[x].v=tr[rs].v;
            tr[x].c=tr[rs].c;
            return ;
        }

    如果右面儿子减少小于左面增加,这是一种比较麻烦的情况,我们维护一个cal函数,专门计算左面儿子v的值

        if(tr[ls].c>tr[rs].cut){
            tr[x].cut=tr[ls].cut;
            tr[x].v=tr[rs].v+ask(ls,tr[rs].cut);
            tr[x].c=tr[rs].c+tr[ls].c-tr[rs].cut;
            return ;
        }

    cal函数具体实现很简单

    当右儿子恰好够减,直接返回左儿子剩余

    右儿子省的多,从右儿子的右儿子搜

    右儿子不够,从左儿子搜

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define A 7200000
    #define ls x<<1
    #define rs x<<1|1
    #define py printf("****
    ")
    struct tree{
        ll l,r,v,c,cut;
    }tr[A];
    ll ceng[A],cu[A];
    ll m,q;
    ll ask(ll x,ll c){
    //    if(c==tr[x].c) return 0;
        if(tr[rs].c==c)
            return tr[x].v-tr[rs].v;
        else if(tr[rs].c>c)
            return tr[x].v-tr[rs].v+ask(rs,c);
        else  return ask(ls,c-tr[rs].c+tr[rs].cut);
    }
    void pushup(ll x){
        if(tr[ls].c<=tr[rs].cut){
            tr[x].cut=tr[rs].cut-tr[ls].c+tr[ls].cut;
            tr[x].v=tr[rs].v;
            tr[x].c=tr[rs].c;
            return ;
        }
        if(tr[rs].cut==0){
            tr[x].v=tr[ls].v+tr[rs].v;
            tr[x].c=tr[ls].c+tr[rs].c;
            tr[x].cut=tr[ls].cut+tr[rs].cut;
            return ;
        }
        if(tr[ls].c>tr[rs].cut){
            tr[x].cut=tr[ls].cut;
            tr[x].v=tr[rs].v+ask(ls,tr[rs].cut);
            tr[x].c=tr[rs].c+tr[ls].c-tr[rs].cut;
            return ;
        }
    }
    void built(ll p,ll l,ll r){
    //    printf("p=%lld l=%lld r=%lld
    ",p,l,r);
        tr[p].l=l,tr[p].r=r;
        if(l==r){
            if(cu[l]) {
                tr[p].cut=ceng[l];
                tr[p].v=0,tr[p].c=0;
                return ;
            }
            if(!cu[l]){
                tr[p].v=ceng[l];
                tr[p].c=1;
                tr[p].cut=0;
                return ;
            }
        }
        
        ll mid=(l+r)>>1;
        built(p<<1,l,mid);
        built(p<<1|1,mid+1,r);
        pushup(p);
    }
    void change(ll x,ll q){
        if(tr[x].l==tr[x].r){
            if(!cu[q]){
                tr[x].v=ceng[q];
                tr[x].c=1;
                tr[x].cut=0;
                return ;
            }
            else{
                tr[x].cut=ceng[q];
                tr[x].v=0,tr[x].c=0;
                return ;
            }
        }
        ll mid=(tr[x].l+tr[x].r)>>1;
        if(mid>=q)
            change(ls,q);
        else 
            change(rs,q);
        pushup(x);
    }
    int main(){
        scanf("%lld%lld",&m,&q);
        for(ll i=1;i<=m;i++){
            scanf("%lld%lld",&cu[i],&ceng[i]);
        }
        built(1,1,m);
    //    printf("tr.c .v=%lld  %lld
    ",tr[2].c,tr[2].v);
    //    printf(".c=%lld v=%lld
    ",tr[3].c,tr[3].v);
    //    printf(".c=%lld
    ",tr[1].v);
        for(ll i=1,a,b,c;i<=q;i++){
            scanf("%lld%lld%lld",&a,&b,&c);
            cu[a]=b;
            ceng[a]=c;
            change(1,a);
    //        printf("p14 v=%lld c=%lld
    ",tr[14].c,tr[14].v);
            printf("%lld
    ",tr[1].v);
        }
    }
    我已没有下降的余地
  • 相关阅读:
    spring源码学习(一) 小小少年
    mysql索引 小小少年
    Java集合框架个人学习笔记 小小少年
    记录一些自己百度到的问题解决方法
    基于内容的医学图像总结
    黑客与画家 第一章
    问题,不是逃避的
    黑客与画家 第二章
    记录最近一周的感受
    暗时间之体会
  • 原文地址:https://www.cnblogs.com/znsbc-13/p/11332552.html
Copyright © 2011-2022 走看看