• 20190803考试反思


      这次考试就不骂自己了,毕竟骂了也没用。T1是水题。。用map手卡30分,我tm。。。。然后以为这就结束了,然后去改T2,T2WA40,我写的主席树但是修改是自己yy的,以为就是错了,然后把离散化去了,WA80?????!!!然后加上WA40。。。。然后我好好研究了一下,突然想到它可能询问从没出现过的颜色,然后判了一句,A了。。。。因为没出现过就是0,主席树查不出来。。。T3考场上吃屎一会再说。

      T1:这是一道规律题,找的话其实打个父亲表,看一下就能知道,一个数的父亲就是这个数之前减去离他最近的斐波数,我们又可以知道这个斐波数增长飞快,见过通项的都知道,这玩意是指数级的,所以就可以打个表知道大概60多个就到13位了,找父亲log60,抬lca是60,一次操作就是常数,m次绝对可以接受,结果忘了之前搞得一个map没删,就死了30分。

      

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;
    long long f[10000];    
    long long rd()
    {
        long long s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    long long fa(long long x)
    {
        long long id=lower_bound(f+1,f+64,x)-f-1;
        return x-f[id];
    }
    long long getdep(long long tmp)
    {
        long long ans=0,x=tmp;
        while(x!=1)
        {
            ++ans;
            x=fa(x);
        }
        return ans;
    }
    long long lca(long long a,long long b)
    {
        int depa=getdep(a),depb=getdep(b);
        if(depa<depb) swap(a,b),swap(depa,depb);
        while(depa>depb) a=fa(a),depa--;
        if(a==b) return a;
        while(fa(a)!=fa(b)) a=fa(a),b=fa(b);
        return fa(a);
    }
    int main()
    {
        f[0]=1;f[1]=1;
        for(int i=2;i<=63;i++)
        {
            f[i]=f[i-1]+f[i-2];
        }
        int m=rd();
        for(int i=1;i<=m;i++)
        {
            long long a=rd(),b=rd();
            if(a==1||b==1)
            {
                puts("1");
                continue;
            }
            printf("%lld
    ",lca(a,b));
        }
        return 0;
    }
    /*
    g++ 1.cpp -o 1
    ./1
    5
    1 1
    2 3
    5 7
    7 13
    4 12
    */
    View Code

      T2:手动修改的主席树,因为这个修改不是修改,是交换,这很重要,那这样后面的主席树都不用改,只改一颗就行了,然后就可以性感询问,在线回复了。还是一样,可持久化烧内存,内存开够就没了。主席树码量极小

      

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=300050;
    int rt[N],a[N],p[N],tt=0,cnt=0;
    struct tree{int lc,rc,w;}tr[50000020];
    int rd()
    {
        int s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    void insert(int &x,int l,int r,int p,int va)
    {
        tr[++tt]=tr[x];x=tt;
        if(l==r)
        {
            tr[x].w+=va;
            return;
        }
        int mid=(l+r)>>1;
        if(p<=mid) insert(tr[x].lc,l,mid,p,va);
        else insert(tr[x].rc,mid+1,r,p,va);
    }
    int query(int x,int l,int r,int p)
    {
        if(l==r)return tr[x].w;
        int mid=(l+r)>>1;
        if(p<=mid)return query(tr[x].lc,l,mid,p);
        else return query(tr[x].rc,mid+1,r,p);
    }
    int main()
    {
        int n=rd(),m=rd();
        for(int i=1;i<=n;i++)
        {
            a[i]=rd();
            if(!p[a[i]]) p[a[i]]=++cnt;
        }
        for(int i=1;i<=n;i++)
        {
            rt[i]=rt[i-1];
            insert(rt[i],1,cnt,p[a[i]],1);
        }
        while(m--)
        {
            int op=rd();
            if(op==1)
            {
                int l=rd(),r=rd(),c=rd();
                if(!p[c]) puts("0");
                else printf("%d
    ",query(rt[r],1,cnt,p[c])-query(rt[l-1],1,cnt,p[c]));
            }
            else 
            {
                int l=rd();
                insert(rt[l],1,cnt,p[a[l]],-1);
                insert(rt[l],1,cnt,p[a[l+1]],1);
                swap(a[l],a[l+1]);
            }
        }
    }
    /*
    g++ 2.cpp -o 2
    ./2
    10 9
    1 2 3 4 5 6 1 2 3 4
    1 1 3 3
    1 4 6 3
    2 3
    1 1 3 3
    1 4 6 3
    1 1 10 4
    1 1 10 3
    1 1 10 2
    1 1 10 1
    */
    View Code

      T3:首先这个题不是DP,倒着扫一遍,贪心找最长的合法区间,然后既能保证最少,也能保证最小。然后k=1的时候好搞,随便搞搞就行了,k=2的时候用二分图来做,我考试的时候鬼畜没看到k只能等于1或2,然后就开始yy,发现如果在一张图上如果把非敌对关系建图(反图)的话,在只有双联通分量里的点才能分成一个小组,于是我就开始了愉快的tarjan。。。。这题k=2的时候二分图可以跑过,我们就可以通过二分图判定,来判断这一堆猫啊不兔子是否能分两组,这个题的打法没怎么见过,不是dp只能瞎打。自己yy了一个调了一下午。

      另外:亲测告诉各位卡常大师,sqrt函数我估计是$O(2^{n})$的,慢到没分数,直接打表比sqrt快3000ms

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    //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++)
    using namespace std;
    const int N=3000050;
    bool v[N],ch[N];
    int c[N],s[N],a[N],tt,qn,tot,fr[N*2];
    struct node{int fr,to,pr;}mo[N*2];
    void add(int x,int y)
    {
        mo[++tt].fr=x;
        mo[tt].to=y;
        mo[tt].pr=fr[x];
        fr[x]=tt;
    }
    bool dfs(const register int x,const register int cl)
    {
        c[x]=cl;
        //cout<<x<<endl;
        for(int i=fr[x];i;i=mo[i].pr)
        {
            const register int to=mo[i].to;
            //cout<<to<<" "<<cl<<endl;
            if(c[to]==cl)return false;
            if(c[to]==0&&!dfs(to,-cl))return false;
        }
        return true;
    }
    int rd()
    {
        int s=0,w=1;
        char cc=getchar();
        while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s*w;
    }
    int main()
    {
        int bm=0;
        int n=rd(),K=rd();
        for(int i=1;i<=512;i++) ch[i*i]=1;
        for(int i=1;i<=n;i++)
            a[i]=rd(),bm=max(bm,a[i]);
        if(K==1)
        {
            for(int i=n;i;)
            {
                bool flag=1;
                int j=i;
                for(;j;j--)
                {
                    for(int k=1;k<=512;k++)
                    {
                        if(v[k*k-a[j]]){flag=0;break;}
                    }
                    if(flag==0) break;
                    v[a[j]]=1;
                }
                for(int k=j;k<=i;k++) v[a[k]]=0;
                i=j;
                if(j!=0) s[++tot]=j;
            }
            printf("%d
    ",tot+1);
            for(int i=tot;i;i--) printf("%d ",s[i]);
            puts("");
            return 0;
        }
        else
        {
            for(int i=n;i;)
            {
                bool flag=1;
                register int j=i;
                for(;j;j--)
                {
                    for(int k=j+1;k<=i;k++)if(ch[a[j]+a[k]])add(j,k),add(k,j);
                    for(int k=j;k<=i;k++)c[k]=0;
                    if(!dfs(j,1))break;
                }
                for(int k=j;k<=i;k++)fr[k]=0;
                i=j;tt=0;
                s[++tot]=j;
            }
            printf("%d
    ",tot);
            for(int i=tot-1;i;i--) printf("%d ",s[i]);
            puts("");
            return 0;
        }
    }
    /*
    g++ 3.cpp -o 3
    ./3
    5 2
    1 3 15 10 6
    */
    View Code

     

  • 相关阅读:
    JSON 在 IE 下不执行的问题
    一些UTF8编码问题
    如果你也想做一个Pinterest?
    关于apache虚拟机的NameVirtualHost错误
    如何玩转数据库设计
    mysql 导入数据时 max_allowed_packet 的问题
    几个练习题
    数组,for语句(补10.11)
    MySql数据库
    js基础(补10.10)
  • 原文地址:https://www.cnblogs.com/starsing/p/11296349.html
Copyright © 2020-2023  润新知