• 分治学习笔记


    这是一个古老的坑了。孩子真不会分治怎么办(雾

    去LOJ上扒了几道题做 主要就是纯分治和CDQ分治 反而点分治 陈老师二分还有分治FFT都还会亚子(我丢 我好难

    JOISC2014 Day 3 稻草人

    分治以后考虑维护上方的递增单调栈,下方的递减单调栈,然后二分位置确定每一个答案就好了。

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 20021225
    #define N 200010
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct poi{int x,y;}p[N];
    bool cmpx(poi a,poi b){return a.x<b.x;}
    bool cmpy(poi a,poi b){return a.y<b.y;}
    int stk1[N],stk2[N],n1,n2; ll fin;
    void solve(int l,int r)
    {
        if(l==r)    return;
        int mid=l+r>>1;
        solve(l,mid); solve(mid+1,r);
        sort(p+l,p+mid+1,cmpx); sort(p+mid+1,p+r+1,cmpx);
        int j=l; n1=n2=0;
        for(int i=mid+1;i<=r;i++)
        {
            while(n2 && p[i].y<p[stk2[n2]].y)    n2--;
            stk2[++n2]=i;
            while(j<=mid && p[j].x<p[i].x)
            {
                while(n1 && p[j].y>p[stk1[n1]].y)    n1--;
                stk1[++n1]=j; j++;
            }
            int lpos=1,rpos=n1,ans=0;
            while(lpos<=rpos)
            {
                int mid=lpos+rpos>>1;
                if(p[stk1[mid]].x>p[stk2[n2-1]].x)
                    ans=mid,rpos=mid-1;
                else    lpos=mid+1;
            }
            if(ans)    fin+=n1-ans+1;
        }
    }
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++)
            p[i].x=read(),p[i].y=read();
        p[0].x=p[0].y=-1; sort(p+1,p+n+1,cmpy);
        solve(1,n); printf("%lld
    ",fin);
        return 0;
    }
    View Code

    「TJOI / HEOI2016」序列

    朴素DP长这样

    $f[i] = max(f[i],f[j]+1)$

    $i>j$ $a[i]>=mx[j]$ $mn[i]>=a[j]$

    一眼三维偏序上CDQ就好啦

    好像裸上树套树的人更多(毒瘤!

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 20021225
    #define N 100010
    #define lowbit(x) (x&-x)
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct node{int a,mx,mn,f,id;}a[N];
    struct bit
    {
        int t[N],n;
        void mfy(int x,int v){while(x<=n) t[x]=max(t[x],v),x+=lowbit(x);}
        int qry(int x){int ans=0; while(x) ans=max(ans,t[x]),x-=lowbit(x); return ans;}
        void del(int x){while(x<=n)    t[x]=0,x+=lowbit(x);}
    }b;
    bool cmpi(node x,node y){return x.id<y.id;}
    bool cmpa(node x,node y){return x.a<y.a;}
    bool cmpn(node x,node y){return x.mn<y.mn;}
    void solve(int l,int r)
    {
        if(l==r)    return; int mid=l+r>>1;
        solve(l,mid);
        sort(a+l,a+mid+1,cmpa); sort(a+mid+1,a+r+1,cmpn);
        int w=l;
        for(int i=mid+1;i<=r;i++)
        {
            while(w<=mid && a[w].a<=a[i].mn)
                b.mfy(a[w].mx,a[w].f),w++;
            a[i].f=max(a[i].f,b.qry(a[i].a)+1);
        }
        for(int i=l;i<w;i++)    b.del(a[i].mx);
        sort(a+mid+1,a+r+1,cmpi);
        solve(mid+1,r);
    }
    int main()
    {
        int n=read(),m=read(); b.n=n;
        for(int i=1;i<=n;i++)    a[i].mn=a[i].mx=a[i].a=read(),a[i].id=i,a[i].f=1;
        for(int i=1;i<=m;i++)
        {
            int x=read(),v=read();
            a[x].mx=max(a[x].mx,v);
            a[x].mn=min(a[x].mn,v);
        }
        solve(1,n); int ans=0;
        for(int i=1;i<=n;i++)    ans=max(ans,a[i].f);
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    【BZOJ2989】数列

    看起来有两个绝对值能想到什么呢!曼哈顿距离!

    简单的转欧式距离就是二维数点啦!

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 20021225
    #define N 600010
    #define nd 250010
    #define lowbit(x) (x&-x)
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct bit
    {
        int t[N],n;
        void modify(int x,int v){while(x<=n)    t[x]+=v,x+=lowbit(x);}
        int query(int x){int ans=0; while(x) ans+=t[x],x-=lowbit(x); return ans;}
        int ask(int x,int y){return query(y)-query(x-1);}
    }b;
    struct node{int type,x,y,k,id;}a[N],tmp[N];
    bool cmpx(node x,node y){return x.x==y.x?x.type>y.type:x.x<y.x;}
    int f[N];
    void solve(int l,int r)
    {
        if(l==r)    return;
        int mid=l+r>>1,t=0; solve(l,mid);
        for(int i=l;i<=mid;i++)    if(!a[i].type)
            tmp[++t]=a[i];
        for(int i=mid+1;i<=r;i++)    if(a[i].type)
        {
            tmp[++t]=(node){+1,a[i].x-a[i].k,a[i].y,a[i].k,a[i].id};
            tmp[++t]=(node){-1,a[i].x+a[i].k,a[i].y,a[i].k,a[i].id};
        }
        sort(tmp+1,tmp+t+1,cmpx);
        for(int i=1;i<=t;i++)
            if(!tmp[i].type)    b.modify(tmp[i].y,1);
            else    f[tmp[i].id]-=tmp[i].type*b.ask(tmp[i].y-tmp[i].k,tmp[i].y+tmp[i].k);
        for(int i=1;i<=t;i++)    if(!tmp[i].type)
            b.modify(tmp[i].y,-1);
        solve(mid+1,r);
    }
    int top,v[N],fq; char ch[20];
    int main()
    {
        int n=read(),q=read(),x,y;
        for(int i=1;i<=n;i++)
            v[i]=read(),a[++top]=(node){0,i+v[i],i-v[i]+nd,0,0};
        for(int i=1;i<=q;i++)
        {
            scanf("%s",ch); x=read(),y=read();
            if(ch[0]=='Q')
                a[++top]=(node){1,x+v[x],x-v[x]+nd,y,++fq};
            else
                v[x]=y,a[++top]=(node){0,x+v[x],x-v[x]+nd,0,0};
        }
        b.n=nd+nd; solve(1,top);
        for(int i=1;i<=fq;i++)
            printf("%d
    ",f[i]);
        return 0;
    }
    View Code

    平面最近点对

    ——孩子发现自己这个都不会,还有救吗?

    ——应该扔了。(逃

    貌似就是分治下去,然后暴力,至于复杂度为什么是对的,好像有证明说这样的点不超过6个?

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 1e18
    #define db double
    #define eps 1e-8
    #define N 200010
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct poi
    {
        db x,y;
        poi(){}
        poi(db _x,db _y){x=_x,y=_y;}
    }p[N],L[N],R[N];
    bool operator<(poi a,poi b){return a.x<b.x;}
    db dis(poi x,poi y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
    void print(poi a){printf("%lf %lf
    ",a.x,a.y);}
    db solve(int l,int r)
    {
        if(l==r)    return inf; int mid=l+r>>1;
        db d1=solve(l,mid),d2=solve(mid+1,r);
        db d=min(d1,d2); int nl=0,nr=0;
        for(int i=mid;i>=l;i--)    if(p[mid].x-p[i].x<=d)
            L[++nl]=p[i]; else    break;
        for(int i=mid+1;i<=r;i++)    if(p[i].x-p[mid].x<=d)
            R[++nr]=p[i]; else    break;
        for(int i=1;i<=nl;i++)    for(int j=1;j<=nr;j++)
            d=min(d,dis(L[i],R[j]));
        return d;
    }
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p+1,p+n+1);
        printf("%.4lf",solve(1,n));
        return 0;
    }
    View Code

    BJWC2011 最小三角形

    经过上个题的经验,于是这个题我直接重新加工了一下,在改变循环顺序,强行剪枝以后依然只能拿到90分的好成绩。

    膜了一发题解,发现好像区别也并不大?把y再排一遍序好像可以降很多复杂度。至于为什么是对的,我也没找到证明。咱也不知道,咱也不敢问。

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 1e18
    #define db double
    #define eps 1e-8
    #define N 200010
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct poi
    {
        db x,y;
        poi(){}
        poi(db _x,db _y){x=_x,y=_y;}
    }p[N],L[N],R[N];
    bool operator<(poi a,poi b){return a.x<b.x;}
    db dis(poi x,poi y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
    void print(poi a){printf("%lf %lf
    ",a.x,a.y);}
    db solve(int l,int r)
    {
        if(l==r)    return inf; int mid=l+r>>1;
        db d1=solve(l,mid),d2=solve(mid+1,r);
        db d=min(d1,d2); int nl=0,nr=0;
        for(int i=mid;i>=l;i--)    if(p[mid].x-p[i].x<=d/2)
            L[++nl]=p[i]; else    break;
        for(int i=mid+1;i<=r;i++)    if(p[i].x-p[mid].x<=d/2)
            R[++nr]=p[i]; else    break;
        for(int i=1;i<=nl;i++)    for(int j=i+1;j<=nl;j++)
            if(dis(L[i],L[j])*2<=d)    for(int k=1;k<=nr;k++)
                d=min(d,dis(L[i],R[k])+dis(L[i],L[j])+dis(L[j],R[k]));
        for(int j=1;j<=nr;j++)    for(int k=j+1;k<=nr;k++)
            if(dis(R[j],R[k])*2<=d)    for(int i=1;i<=nl;i++)
                d=min(d,dis(L[i],R[k])+dis(L[i],R[j])+dis(R[j],R[k]));
        return d;
    }
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p+1,p+n+1);
        printf("%.6lf",solve(1,n));
        return 0;
    }
    90pts
    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 1e18
    #define db double
    #define eps 1e-8
    #define N 200010
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    struct poi
    {
        db x,y;
        poi(){}
        poi(db _x,db _y){x=_x,y=_y;}
    }p[N],w[N];
    bool operator<(poi a,poi b){return a.x<b.x;}
    bool cmpy(poi a,poi b){return a.y<b.y;}
    db dis(poi x,poi y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
    void print(poi a){printf("%lf %lf
    ",a.x,a.y);}
    db solve(int l,int r)
    {
        if(l==r)    return inf; int mid=l+r>>1;
        db d1=solve(l,mid),d2=solve(mid+1,r);
        db d=min(d1,d2),lim=d/2; int nw=0;
        for(int i=mid;i>=l;i--)    if((p[mid].x-p[i].x)<=lim)
            w[++nw]=p[i]; else    break;
        for(int i=mid+1;i<=r;i++)    if((p[i].x-p[mid].x)<=lim)
            w[++nw]=p[i]; else    break;
        sort(w+1,w+nw+1,cmpy);
        for(int i=1,j=1;i<=nw;i++)
        {
            while(j<=nw && (w[j].y-w[i].y)<=lim)
                j++;
            for(int k=i+1;k<j;k++)    for(int l=k+1;l<j;l++)
                d=min(d,dis(w[i],w[k])+dis(w[i],w[l])+dis(w[l],w[k]));
        }
        return d;
    }
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p+1,p+n+1);
        printf("%.6lf",solve(1,n));
        return 0;
    }
    100pts
  • 相关阅读:
    Python Install for windows X64
    CentOS 7 Install Gitlab CE
    centos 7安装vmtools时提示The path "" is not a valid path to the xxx kernel headers.
    Jenkins install
    gradle 编译 No such property: sonatypeUsername错误解决
    Hololens 开发环境配置(转)
    Krapo 2
    Krapno 1
    dubbo 常见错误
    groupby
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/11579027.html
Copyright © 2020-2023  润新知