• 两次考试


    10.22

    T1

    异或支持一些律,把后面的移到前面就行了

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    const int N=100006;
    inline void readint(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    
    int n;
    int f[N],g[N];
    
    int main(){
    
        //freopen("T1.in","r",stdin);
        //freopen("T1.out","w",stdout);
    
        rint i,j;
    
        readint(n);
        for(i=0;i<n;++i) readint(f[i]);
        for(i=0;i<n;++i) readint(g[i]);
        int tt=0;
        for(i=0;i<n;++i)
        {
            tt=(tt^(f[i]^g[i]));
            printf("%d ",tt);
        }
    }
    T1

    T2

    对于只有1、2的情况

    ans就是最底下一层最中间开始数到左右两边最近的连续的一段

    推广到1~n

    可以二分一个值,把比它小的设成1,大于等于的设成2,就可以O(n)求出来结果

    是1,说明ans比二分的这个值小

    否则,就大于等于

    其实数据比较水,对中间三个排序,输出中位数就A了...

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    const int N=100006;
    inline void readint(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    
    int n;
    int f[N],g[N];
    
    int main(){
    
        //freopen("T1.in","r",stdin);
        //freopen("T1.out","w",stdout);
    
        rint i,j;
    
        readint(n);
        for(i=0;i<n;++i) readint(f[i]);
        for(i=0;i<n;++i) readint(g[i]);
        int tt=0;
        for(i=0;i<n;++i)
        {
            tt=(tt^(f[i]^g[i]));
            printf("%d ",tt);
        }
    }
    T2正解

    T3

    考试有思想,但是没打出来

    先把T2的边在T1上进行线段覆盖

    如果T1上有只覆盖1层的,就可以用它来满足覆盖它的那个边

    都满足就YES,否则NO

    #pragma GCC optimize("O3")
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    const int N=200006;
    const int INF=1000000000;
    int first[N],nt[N],ver[N],e;
    inline void addbian(int u,int v)
    {
        ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int T;
    int n;
    int u[N],v[N];
    
    int mn[N*5],sum[N*5],jiid[N*5],jiv[N*5];
    int L,R,oo,vv,pos,id;
    inline void add(int l,int r,int x)
    {
        if(L<=l&&r<=R)
        {
            mn[x]+=vv;
            sum[x]+=(oo*(r-l+1));
            jiv[x]+=vv;
            jiid[x]+=oo;
            return ;
        }
    
        int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
    
        if(jiid[x])
        {
            jiid[ls]+=jiid[x];
            jiid[rs]+=jiid[x];
            sum[ls]+=jiid[x]*(mid-l+1);
            sum[rs]+=jiid[x]*(r-mid);
            jiid[x]=0;
        }
        if(jiv[x])
        {
            jiv[ls]+=jiv[x];
            jiv[rs]+=jiv[x];
            mn[ls]+=jiv[x];
            mn[rs]+=jiv[x];
            jiv[x]=0;
        }
    
        if(L<=mid) add(l,mid,ls);
        if(mid<R) add(mid+1,r,rs);
    
        mn[x]=(mn[ls]<mn[rs]?mn[ls]:mn[rs]);
        sum[x]=sum[ls]+sum[rs];
    }
    inline void qq(int l,int r,int x)
    {
        if(l==r)
        {
            if(mn[x]==1) mn[x]=INF,pos=l,id=sum[x];
            return ;
        }
        int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
        if(jiid[x])
        {
            jiid[ls]+=jiid[x];
            jiid[rs]+=jiid[x];
            sum[ls]+=jiid[x]*(mid-l+1);
            sum[rs]+=jiid[x]*(r-mid);
            jiid[x]=0;
        }
        if(jiv[x])
        {
            jiv[ls]+=jiv[x];
            jiv[rs]+=jiv[x];
            mn[ls]+=jiv[x];
            mn[rs]+=jiv[x];
            jiv[x]=0;
        }
    
        if(mn[ls]==1) qq(l,mid,ls);
        else qq(mid+1,r,rs);
    
        mn[x]=(mn[ls]<mn[rs]?mn[ls]:mn[rs]);
        sum[x]=sum[ls]+sum[rs];
    }
    
    int fa[N],dep[N],size[N],son[N];
    inline void dfs1(int x)
    {
        size[x]=1;
        for(int i=first[x];i!=-1;i=nt[i])
        {
            if(ver[i]==fa[x])
                continue;
            fa[ver[i]]=x;
            dep[ver[i]]=dep[x]+1;
            dfs1(ver[i]);
            size[x]+=size[ver[i]];
            if(size[son[x]]<size[ver[i]])
                son[x]=ver[i];
        }
    }
    int top[N],zheng[N],timer;
    inline void dfs2(int x,int tp)
    {
        top[x]=tp; zheng[x]=++timer;
        if(son[x])
            dfs2(son[x],tp);
        for(int i=first[x];i!=-1;i=nt[i])
        {
            if(ver[i]==fa[x]||ver[i]==son[x])
                continue;
            dfs2(ver[i],ver[i]);
        }
    }
    inline void ADD(int x,int y)
    {
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy])
            {
                x^=y; y^=x; x^=y;
                fx^=fy; fy^=fx; fx^=fy;
            }
            L=zheng[fx]; R=zheng[x];
            add(1,n,1);
            x=fa[fx];
            fx=top[x];
        }
        if(dep[x]>dep[y]) x^=y,y^=x,x^=y;
        if(x!=y) L=zheng[x]+1,R=zheng[y],add(1,n,1);
    }
    
    inline int work()
    {
        mem(ver,0); mem(first,-1); mem(nt,0); e=0;
        mem(son,0); mem(size,0);
        timer=0;
        mem(mn,0); mem(sum,0); mem(jiv,0); mem(jiid,0);
        rint i,j; int tin1,tin2;
        for(i=1;i<n;++i)
        {
            read(tin1); read(tin2);
            addbian(tin1,tin2);
            addbian(tin2,tin1);
        }
        for(i=1;i<n;++i)
            read(u[i]), read(v[i]);
        fa[1]=-1; dep[1]=0;
        dfs1(1);
        dfs2(1,1);
        L=1; R=1; vv=INF; oo=0;
        add(1,n,1);
        for(i=1;i<n;++i)
            oo=i,vv=1,ADD(u[i],v[i]);
        for(i=1;i<n;++i)
        {
            id=0; pos=0;
            qq(1,n,1);
            if(!id) return 0;
            oo=-id; vv=-1;
            ADD(u[id],v[id]);
        }
        return 1;
    }
    
    int main(){
        
        //freopen("T3.in","r",stdin);
    
        //freopen("tree13.in","r",stdin);
    
        read(T);
        while(T--)
        {
            read(n);
            if(work())
                printf("YES
    ");
            else
                printf("NO
    ");
        }
    }
    T3

    10.23

    T1

    有两种做法

    (1) 

    二分答案,用并查集维护,复杂度$O(n^2logn)$

    当然,你需要韩门神的疯狂剪枝和超小常数...

    (2)

    对每一个星星和上下两个边界进行两两连边,边权是他们之间的距离

    跑最小生成树(prim),再找从上边界到下边界的路径上的最小值/2即可

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define dd double
    #define rint register int
    //#define dis(x3,y3,x4,y4) (sqrt((y3-y4)*(y3-y4)+(x3-x4)*(x3-x4)))
    #define esp 0.0000001
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    const int MAXK=10006;
    int first[MAXK*3],nt[MAXK*3],ver[MAXK*3],e;
    dd w[MAXK*3];
    void addbian(int u,int v,dd _w)
    {
        ver[e]=v;
        w[e]=_w;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,m,K;
    int x[MAXK+100],y[MAXK+100];
    dd mn[MAXK+100];
    bool ff[MAXK+100];
    int pr[MAXK+100];
    
    inline dd dis(int f1,int f2)
    {
        if( (f1==0&&f2==K+1)||(f1==K+1&&f2==0) ) return m;
        if(f1==0) return y[f2];
        if(f1==K+1) return m-y[f2];
        if(f2==0) return y[f1];
        if(f2==K+1) return m-y[f1];
        return sqrt((y[f1]-y[f2])*(y[f1]-y[f2])+(x[f1]-x[f2])*(x[f1]-x[f2]));
    }
    
    dd an[MAXK+100];
    void dfs(int x)
    {
        for(int i=first[x];i!=-1;i=nt[i])
        {
            if(an[ver[i]]>w[i])
                an[ver[i]]=w[i];
            dfs(ver[i]);
        }
    }
    
    dd work()
    {
        rint i,j; int all=K+1;
        
        for(i=all+1;i>=0;--i) mn[i]=an[i]=0x7fffffff;
        mn[0]=0;
        int tt; dd vv;
        for(i=0;i<=all;++i)
        {
            tt=all+1;
            for(j=0;j<=all;++j)
                if(!ff[j]&&mn[tt]>mn[j])
                    tt=j;
            ff[tt]=1;
            //printf("i=%d tt=%d
    ",i,tt);
            for(j=0;j<=all;++j)
                if(!ff[j])
                {
                    vv=dis(tt,j);
                    //printf("j=%d vv=%lf
    ",j,vv);
                    if(mn[j]>vv)
                      mn[j]=vv,pr[j]=tt;
                }
        }
        for(i=1;i<=all;++i)
            addbian(pr[i],i,mn[i]);
        dfs(0);
        return an[all]/2.0;
    }
    
    int main(){
        
        freopen("T1.in","r",stdin);
        //freopen("T1.out","w",stdout);
        
        mem(first,-1);
        
        rint i,j;
        
        read(n); read(m); read(K);
        for(i=1;i<=K;++i) read(x[i]),read(y[i]);
        printf("%.8lf",work());
    }
    解1
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define dd double
    #define rint register int
    //#define dis(x3,y3,x4,y4) (sqrt((y3-y4)*(y3-y4)+(x3-x4)*(x3-x4)))
    #define esp 0.0000001
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    inline void readll(ll &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    const int MAXK=10006;
    int first[MAXK*3],nt[MAXK*3],ver[MAXK*3],e;
    ll w[MAXK*3];
    void addbian(int u,int v,ll _w)
    {
        ver[e]=v;
        w[e]=_w;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,m,K;
    ll x[MAXK+100],y[MAXK+100];
    ll mn[MAXK+100],ans;
    bool ff[MAXK+100];
    int pr[MAXK+100];
    
    inline ll dis(int f1,int f2)
    {
        if(f1>f2) f1^=f2,f2^=f1,f1^=f2;
        if(f1==K+1&&f2==K+2) return (ll)m*m;
        if(f2==K+1) return y[f1]*y[f1];
        if(f2==K+2) return ((ll)m-y[f1])*((ll)m-y[f1]);
        return (y[f1]-y[f2])*(y[f1]-y[f2])+(x[f1]-x[f2])*(x[f1]-x[f2]);
    }
    
    void dfs(int x,int fa,ll ww)
    {
        if(x==K+2)
        {
            ans=ww;
            return ;
        }
        for(int i=first[x];i!=-1;i=nt[i])
        {
            if(ver[i]==fa)
                continue;
            dfs(ver[i],x,max(ww,w[i]));
        }
    }
    
    dd work()
    {
        rint i,j; int all=K+2;
        
        mem(mn,0x7f);
        mn[K+1]=0;
        int tt; ll vv;
        for(i=1;i<=all;++i)
        {
            tt=0;
            for(j=1;j<=all;++j)
                if(!ff[j]&&mn[tt]>mn[j])
                    tt=j;
            ff[tt]=1;
            if(pr[tt])
                addbian(pr[tt],tt,mn[tt]),
                addbian(tt,pr[tt],mn[tt]);
            for(j=1;j<=all;++j)
                if(!ff[j])
                {
                    vv=dis(tt,j);
                    if(mn[j]>vv)
                      mn[j]=vv,pr[j]=tt;
                }
        }
        dfs(K+1,-1,0);
        return sqrt(ans)/2.0;
    }
    
    int main(){
        
        //freopen("T1.in","r",stdin);
        //freopen("T1.out","w",stdout);
        
        //freopen("in.in","r",stdin);
        
        mem(first,-1);
        
        rint i,j;
        
        read(n); read(m); read(K);
        for(i=1;i<=K;++i) readll(x[i]),readll(y[i]);
        printf("%.8lf",work());
    }
    2

    T2

    首先你可以暴搜(虽然我暴搜也打挂了),有20分

    然后你发现,题目其实是让求一个极长的上升序列,可以$O(n^2)$dp,有40分

    然后你又发现可以有一个加calc的$O(nlog^2n)$的线段树优化

    这个calc的写法其实跟以前 金坷垃、treap、楼房建设 差不多

    一般是 维护三个域

    ans、由于两个子区间不可加性的辅助转移的变量、记录状态防止超时的量

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define dd double
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    const int N=200006;
    
    struct son
    {
        int pos,p,c;
        bool friend operator < (son a,son b)
        {
            return a.p<b.p;
        }
    }ji[N];
    
    int n,INF;
    
    int an[N*4],mx[N*4],ban[N*4];
    int cal(int hi,int l,int r,int x)
    {
        if(hi>mx[x]) return INF;
        if(l==r) return an[x];
        int mid=(l+r)>>1;
        if(hi>mx[x<<1|1]) return cal(hi,l,mid,x<<1);
        else return min(ban[x<<1],cal(hi,mid+1,r,x<<1|1));
    }
    void change(int pos,int hh,int vv,int l,int r,int x)
    {
        if(l==r)
        {
            an[x]=vv; mx[x]=hh;
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) change(pos,hh,vv,l,mid,x<<1);
        else change(pos,hh,vv,mid+1,r,x<<1|1);
        mx[x]=max(mx[x<<1],mx[x<<1|1]);
        an[x]=min(an[x<<1|1],ban[x<<1]=cal(mx[x<<1|1],l,mid,x<<1));
    }
    void qq(int L,int R,int &ans,int &hi,int l,int r,int x)
    {
        //printf("L=%d R=%d ans=%d hi=%d l=%d r=%d x=%d
    ",L,R,ans,hi,l,r,x);
        if(L>R) return ;
        if(L<=l&&r<=R)
        {
            ans=min(ans,cal(hi,l,r,x));
            hi=max(hi,mx[x]);
            return ;
        }
        int mid=(l+r)>>1;
        if(mid<R)
            qq(L,R,ans,hi,mid+1,r,x<<1|1);
        if(L<=mid)
            qq(L,R,ans,hi,l,mid,x<<1);
    }
    
    int f[N];
    
    int work()
    {
        rint i,j; int tt,hi;
        sort(ji+1,ji+1+n);
        mem(an,0x7f); mem(ban,0x7f); mem(&INF,0x7f);
        for(i=1;i<=n;++i)
        {
            //printf("i=%d
    ",i);
            hi=0; tt=INF;
            qq(1,ji[i].pos-1,tt,hi,1,n,1);
            if(tt==INF) tt=0;
            f[ji[i].pos]=tt+ji[i].c;
            change(ji[i].pos,ji[i].p,f[ji[i].pos],1,n,1);
        }
        /*printf("
    ");
        for(i=1;i<=n;++i)
            printf("%d ",f[i]);
        printf("
    ");*/
        return f[n];
    }
    
    int main(){
        
        //freopen("T2.in","r",stdin);
        //freopen("T2.out","w",stdout);
        
        rint i,j;
        
        read(n);
        for(i=1;i<=n;++i) ji[i].pos=i,read(ji[i].p);
        for(i=1;i<=n;++i) read(ji[i].c);
        ++n; ji[n].pos=n; ji[n].c=0; ji[n].p=0x7fffffff;
        cout<<work();
    }
    T2

    T3

    可以把式子变成一个类似于斜率的式子,之后就转变成求一个下凸壳

    用可持久化单调栈维护

    可持久化?

    其实就是一个回溯的过程

    弹栈还要二分弹,暴力弹会被卡成$O(n^2)$

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define dd double
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; char q=getchar();
        while(q<'0'||q>'9') q=getchar();
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
    }
    const int N=500006;
    int first[N*3],nt[N*3],ver[N*3],e;
    void addbian(int u,int v)
    {
        ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n;
    int c[N],dep[N];
    int zhan[N*2],he;
    dd an[N];
    
    inline dd cross(int q,int w)
    {
        return (dd)(c[w]-c[q])/(dd)(dep[w]-dep[q]);
    }
    
    int er(int l,int r,int order)
    {
        int mid,tt,ans=r;
        while(l<=r)
        {
            mid=(l+r)>>1;
            tt=(cross(zhan[mid],order)<cross(zhan[mid-1],order));
            if(tt) ans=mid-1,r=mid-1;
            else l=mid+1;
        }
        return ans;
    }
    
    void dfs(int x)
    {
        int pr,prv;
        ++he;
        prv=zhan[he];
        zhan[he]=x;
        pr=he;
        for(int i=first[x];i!=-1;i=nt[i])
        {
            dep[ver[i]]=dep[x]+1;
            if(he>1)
                he=er(2,he,ver[i]);
            an[ver[i]]=-cross(zhan[he],ver[i]);
            dfs(ver[i]);
            he=pr;
        }
        zhan[he]=prv;
    }
    
    int main(){
        
        //freopen("T3.in","r",stdin);
        
        rint i,j;
        
        mem(first,-1);
        
        read(n);
        int tin;
        for(i=1;i<=n;++i) read(c[i]);
        for(i=2;i<=n;++i)
        {
            read(tin);
            addbian(tin,i);
        }
        dep[1]=1;
        dfs(1);
        for(i=2;i<=n;++i)
            printf("%.10lf
    ",an[i]);
    }
    T3
  • 相关阅读:
    网页返回码大全
    求数组中子数组的最大和
    什么是面向对象?面向对象与面向过程的区别?
    Java内部类
    Java拆箱装箱
    linux中su和sudo区别
    Linux 中账户管理
    解决warn appiumdoctor bin directory for $java_home is not set
    Moco之include
    Mock server 之 Moco的使用
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7721702.html
Copyright © 2020-2023  润新知