zoukankan      html  css  js  c++  java
  • 20190922

    还是好虚。

    十天之前开始发烧,烧了好多天,然后就给我烧虚了。感冒,发烧,头痛牙痛腿痛。

    考试也连爆了,已经滚出一机房了。

    ……

    这次考试也挺有意思。

    T1暴力都不会。

    T3暴力都不会。

    T2只会莫队骗分。

    结果T2只想骗60的程序A了?

    数据真水。

    我真垃圾。

    T1

    暴力是个$Theta(N^3)$傻逼暴力,然而考试的时候并没有想到。

    正解单调栈+dp。

    大模拟填坑也能A,还飞快……

    其实挺水的。

    #include<cstdio>
    #include<cmath>
    #define ll long long
    using namespace std;
    int const N=1e6+5;
    inline int read(){
        int ss=0;char bb=getchar();
        while(bb<48||bb>57)bb=getchar();
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss;
    }
    int n,top=1;
    int h[N],stack[N];
    ll C,w[N],wf[N],dp[N];
    inline int _abs(int x){
        return x<0?-x:x;
    }
    inline ll max(ll x,ll y){
        return x>y?x:y;
    }
    inline ll min(ll x,ll y){
        return x<y?x:y;
    }
    ll find(ll x,ll l,ll r){
        ll a=r-l-1,b=-(w[r-1]-w[l]<<1),c=wf[r-1]-wf[l];
        b-=(l?C:0)+(r!=n?C:0),c+=C*((l?h[l]:0)+(r!=n?h[r]:0));
        x=min(max((ll)(double)b/(-2.0*a)+0.5,x),min(h[l],h[r]));
        return a*x*x+b*x+c;
    }
    signed main(){
        n=read(),C=read();
        for(register int i=1;i<=n;++i)
            w[i]=(h[i]=read())+w[i-1],wf[i]=wf[i-1]+1ll*h[i]*h[i];
        h[0]=h[++n]=1e9+7;
        for(register int i=1;i<=n;++i){
            dp[i]=(i==1||i==n)?dp[i-1]:(dp[i-1]+C*_abs(h[i]-h[i-1]));
            while(top^1 && h[stack[top]]<=h[i])                   if(top--!=1)dp[i]=min(dp[i],dp[stack[top]]+find(h[stack[top+1]],stack[top],i));
            stack[++top]=i;
        }
        printf("%lld",dp[n]);
        return 0;
    }
    View Code

    T2

    用莫队水过的,真没啥好说的。

    题目是个四维偏序,可以CDQ嵌套,也可以打个多维树状数组。

    %%%skyh,%%%yxs,都是打正解的巨神。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int const N=202;
    inline int read(){
        int ss=0;char bb=getchar();
        while(bb<48||bb>57)bb=getchar();
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss;
    }
    inline int min(int x,int y){
        return x<y?x:y;
    }
    inline int max(int x,int y){
        return x>y?x:y;
    }
    inline int ml(int x){
        return x*x-(x-1)*(x-1);
    }
    inline int dl(int x){
        return (x+1)*(x+1)-x*x;
    }
    int r,c,qs,tot,cnt=1;
    int bl[N][N],a[N][N];
    int v[N*N],bar[N*N],now;
    int as[100005];
    struct node{
        int xo,yo,xi,yi,id;
    }q[100005];
    struct ljj{
        int w,xp,yp;
    }sj[N*N];
    int main(){
        r=read(),c=read(),qs=read();
        int rs=1,cs=1;
        for(register int i=1;i<=r;++i)
            for(register int j=1;j<=c;++j)
                sj[++tot].xp=i,sj[tot].yp=j,sj[tot].w=read();
        sort(sj+1,sj+tot+1,[](ljj skyh,ljj yxs){
            return skyh.w<yxs.w;
        });
        a[sj[1].xp][sj[1].yp]=1;
        for(register int i=2;i<=tot;++i)
            a[sj[i].xp][sj[i].yp]=cnt=cnt+(sj[i].w!=sj[i-1].w);
        int xlit=ceil((double)c/cs),ylit=ceil((double)r/rs);
        for(register int i=1,xl,xr=0,ct=0;i<=xlit;++i){
            xl=xr+1,xr=min(xr+cs,c);
            for(register int j=1,yl,yr=0;j<=ylit;++j){
                yl=yr+1,yr=min(yr+rs,r),++ct;
                for(register int k=yl;k<=yr;++k)
                    for(register int u=xl;u<=xr;++u)
                        bl[k][u]=ct;
            }
        }
        for(register int i=1;i<=qs;++i)
            q[i].id=i,q[i].xo=read(),q[i].yo=read(),q[i].xi=read(),q[i].yi=read();
        sort(q+1,q+qs+1,[](node skyh,node yxs){
            return (bl[skyh.xo][skyh.yo]^bl[yxs.xo][yxs.yo])?(bl[skyh.xo][skyh.yo]<bl[yxs.xo][yxs.yo]):(bl[skyh.xi][skyh.yi]>bl[yxs.xi][yxs.yi]);
        });
        int nxo(0),nyo(0),nxi(0),nyi(0),ans(0);
        for(register int i=1;i<=qs;++i){
            int jx=min(q[i].xi,nxi)-max(q[i].xo,nxo)+1,jy=min(q[i].yi,nyi)-max(q[i].yo,nyo)+1;
            if(jx<=0 || jy<=0 || (nxi-nxo+1)*(nyi-nyo+1)-(jx*jy<<1)>=0){
                nxo=q[i].xo,nyo=q[i].yo,nxi=q[i].xi,nyi=q[i].yi;
                ++now,ans=0;
                for(register int j=nxo;j<=nxi;++j)
                    for(register int k=nyo;k<=nyi;++k)
                        if(v[a[j][k]]!=now)v[a[j][k]]=now,bar[a[j][k]]=1,++ans;
                        else ans+=ml(++bar[a[j][k]]);
                as[q[i].id]=ans;
                continue;
            }
            while(nxo<q[i].xo){
                for(register int j=nyo;j<=nyi;++j){
                    ans-=dl(--bar[a[nxo][j]]);
                    if(!bar[a[nxo][j]])v[a[nxo][j]]=now-1;
                }
                ++nxo;
            }
            while(nyo<q[i].yo){
                for(register int j=nxo;j<=nxi;++j){
                    ans-=dl(--bar[a[j][nyo]]);
                    if(!bar[a[j][nyo]])v[a[j][nyo]]=now-1;
                }
                ++nyo;
            }
            while(nxi>q[i].xi){
                for(register int j=nyo;j<=nyi;++j){
                    ans-=dl(--bar[a[nxi][j]]);
                    if(!bar[a[nxi][j]])v[a[nxi][j]]=now-1;
                }
                --nxi;
            }
            while(nyi>q[i].yi){
                for(register int j=nxo;j<=nxi;++j){
                    ans-=dl(--bar[a[j][nyi]]);
                    if(!bar[a[j][nyi]])v[a[j][nyi]]=now-1;
                }
                --nyi;
            }
            while(nxo>q[i].xo){
                --nxo;
                for(register int j=nyo;j<=nyi;++j)
                    if(v[a[nxo][j]]!=now)++ans,v[a[nxo][j]]=now,bar[a[nxo][j]]=1;
                    else ans+=ml(++bar[a[nxo][j]]);
            }
            while(nyo>q[i].yo){
                --nyo;
                for(register int j=nxo;j<=nxi;++j)
                    if(v[a[j][nyo]]!=now)++ans,v[a[j][nyo]]=now,bar[a[j][nyo]]=1;
                    else ans+=ml(++bar[a[j][nyo]]);
            }
            while(nxi<q[i].xi){
                ++nxi;
                for(register int j=nyo;j<=nyi;++j)
                    if(v[a[nxi][j]]!=now)++ans,v[a[nxi][j]]=now,bar[a[nxi][j]]=1;
                    else ans+=ml(++bar[a[nxi][j]]);
            }
            while(nyi<q[i].yi){
                ++nyi;
                for(register int j=nxo;j<=nxi;++j)
                    if(v[a[j][nyi]]!=now)++ans,v[a[j][nyi]]=now,bar[a[j][nyi]]=1;
                    else ans+=ml(++bar[a[j][nyi]]);
            }
            as[q[i].id]=ans;
        }
        for(register int i=1;i<=qs;++i)printf("%d
    ",as[i]);
        return 0;
    }
    View Code

    T3

    两个直径分别为$l_1$和$l_2$的联通块合并后直径最小为$max(lceilfrac{l_1}{2} ceil+lceilfrac{l_2}{2} ceil+1,max(l_1,l_2))$

    知道这个结论就很好做了。

    先找出原树的直径,求出每个点对于直径两端点所形成子树的直径大小。

    然后枚举边,$Theta(1)$求出合并后最小的直径大小,更新答案。

    对于连边方案,如果ans与原树直径相等直接断开重连。

    否则连接两个联通块直径的中点即可。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const N=3e5+5;
    inline int read(){
        int ss=0;char bb=getchar();
        while(bb<48||bb>57)bb=getchar();
        while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
        return ss;
    }
    inline int max(int x,int y){
        return x>y?x:y;
    }
    int n,mp=-1,st,ed,ans=1e9+7,kx,ms,ct=0;
    int head[N],Next[N<<1],to[N<<1],t=1;
    int q[N],qj[N];
    int pre[N];
    char vis[N<<1];
    int stl[N],edl[N];
    inline void add(int x,int y){
        to[++t]=y;
        Next[t]=head[x],head[x]=t;
        return ;
    }
    void dfs(int x,int y,int ds){
        if(ds>mp)mp=ds,st=x;
        ++ds;
        for(int i=head[x];i;i=Next[i])
            if(to[i]^y && i^ct && i^1^ct)dfs(to[i],x,ds);
        return ;
    }
    int bfs(int x){
        memset(pre,0,sizeof(pre));
        int u(0),v(1);
        q[1]=x,pre[x]=-1;
        while(u^v && v^n){
            x=q[++u];
            for(register int i=head[x];i;i=Next[i])
                if(!pre[to[i]] && i^ct && i^1^ct)pre[q[++v]=to[i]]=i^1;
        }
        return v;
    }
    int get(int x,int y,bool p){
        int mad(0),mal(0);
        for(int i=head[x];i;i=Next[i])
            if(to[i]^y){
                int z=get(to[i],x,p)+1;
                mal=max(max(mal,(p?stl[to[i]]:edl[to[i]])),mad+z);
                mad=max(mad,z);
            }
        (p?stl[x]:edl[x])=mal;
        return mad;
    }
    inline void find(int x){
        printf("
    %d %d ",to[x],to[x^1]);
        ct=x,mp=-1;
        dfs(to[x],0,0);
        q[ms=1]=q[bfs(st)];
        for(register int i=pre[q[1]];~i;i=pre[to[i]])
            q[++ms]=to[i];
        printf("%d ",q[ms+1>>1]);
        mp=-1;
        dfs(to[x^1],0,0);
        q[ms=1]=q[bfs(st)];
        for(register int i=pre[q[1]];~i;i=pre[to[i]])
            q[++ms]=to[i];
        printf("%d ",q[ms+1>>1]);
        return ;
    }
    int main(){
        n=read();
        for(register int i=1,ff,tt;i<n;++i)ff=read(),tt=read(),add(ff,tt),add(tt,ff);
        dfs(1,0,0),bfs(st);
        for(register int i=pre[ed=q[n]];~i;i=pre[to[i]])
            vis[i]=1,++ms;
        get(st,0,1),get(ed,0,0);
        for(register int i=2;i<=t;i+=2)
            if(vis[i]){
                int x=edl[to[i]],y=stl[to[i^1]],now=max((x+1>>1)+(y+1>>1)+1,max(x,y));
                if(ans>now)ans=now,qj[kx=1]=i>>1;
                else if(ans==now)qj[++kx]=i>>1;
            }
            else if(vis[i^1]){
                int x=stl[to[i]],y=edl[to[i^1]],now=max((x+1>>1)+(y+1>>1)+1,max(x,y));
                if(ans>now)ans=now,qj[kx=1]=i>>1;
                else if(ans==now)qj[++kx]=i>>1;
            }
            else if(ans>ms)ans=ms,qj[kx=1]=i>>1;
            else if(ans==ms)qj[++kx]=i>>1;
        printf("%d
    %d ",ans,kx);
        for(register int i=1;i<=kx;++i)printf("%d ",qj[i]);
        find(qj[1]<<1);
        return 0;
    }
    View Code
  • 相关阅读:
    C51学习 之 中断
    C51学习 之 动态数码管
    C51学习 之 LED流水灯
    锁存器 工作功能
    keil 5下载地址
    成本与利润最大化问题
    记一次VS下LINK1169的错误
    合并链表
    设计推特
    线段求交点
  • 原文地址:https://www.cnblogs.com/remarkable/p/11575033.html
Copyright © 2011-2022 走看看