1 条题解

  • 0
    @ 2026-5-1 1:02:14

    好题,我懂得欣赏。

    思路

    首先 44 个点可以整个平面覆盖,于是只可能选择 4\le4 个点,设选择 kk 个点。

    k=0k=0 代价为 ipi\sum\limits_{i} p_i

    k=4k=4 代价为前 44 小的 cic_i

    k=1,2k=1,2 直接枚举选择的点,离散化后前缀和可以 O(1)O(1) 算出代价。

    k=3k=3 此时我们不能枚举了,但是认真分析一下只有以下几种情况。

    1. 存在两个点覆盖的区域无交,直接枚举第三个点,对于每个点先算出其代价,再枚举两个点的分界线后取前后缀最小值即可。
    2. 存在一个点满足与其覆盖区域相对的区域没被覆盖,枚举这个点,剩下的两个象限是独立的,我们可以对于每个点算出其对某个象限的代价后取最小值,注意这里要维护次小值,因为两个象限取的点可能相同。
    3. 存在一个点满足另外两个点都在其覆盖的区域内且方向与其相对,此时这个点覆盖的区域和与其相对的区域都被覆盖,因此还是可以将另外两个象限独立处理,同上。
    4. 存在两个点方向相对且相互覆盖,且另外一个点覆盖了剩下两个区域中的一个,枚举这两个点,对于剩下的点,我们只需要其满足能覆盖一个区域,因此符合条件的点是一个二维前缀,维护二维前缀最小值即可,因为可能会与枚举的两个点重复,因此这里要维护次小值和次次小值。

    实现的时候可以每做一遍将平面旋转一次,可以少吃很多史。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    using ll=long long;
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<23],*p1=buf,*p2=buf;
    int read(){int p=0,flg=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-') flg=-1;c=getchar();}while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}return p*flg;}
    int n,m;ll B,s[4][1010][1010],t[3][1010][1010],pre[1010],suf[1010];struct Info{int x,y;ll v;}a[1010],b[100010],tmpa[1010],tmpb[100010];vector<int>X,Y;
    struct Mi{array<ll,2>mi[3];Mi(){for(int i:{0,1,2}) mi[i]={(ll)1e18,0};}}hyw[1010][1010];
    Mi merge(Mi x,Mi y){
        array<ll,2>a[6]={x.mi[0],x.mi[1],x.mi[2],y.mi[0],y.mi[1],y.mi[2]};sort(a,a+6);
        Mi z;int k=0;z.mi[k++]=a[0];for(int i=1;i<6&&k<3;i++) if(z.mi[k-1][1]^a[i][1]) z.mi[k++]=a[i];return z;
    }
    /*
                |
        1       |       3
                |
                |
    ------------|---------------
                |
                |
        0       |       2
                |
                |
    */
    ll sub1(){ll res=1e18;for(int i=1;i<=n;i++) for(int o:{0,1,2,3}) res=min(res,a[i].v+B-s[o][a[i].x][a[i].y]);return res;}
    ll calc(int x,int y,int p,int q){
        int lx=0,rx=X.size(),ly=0,ry=Y.size();
        auto upd=[&](int x,int o){
            if(!o) rx=min(rx,a[x].x),ry=min(ry,a[x].y);
            else if(o==1) rx=min(rx,a[x].x),ly=max(ly,a[x].y);
            else if(o==2) lx=max(lx,a[x].x),ry=min(ry,a[x].y);
            else lx=max(lx,a[x].x),ly=max(ly,a[x].y);
        };upd(x,p);upd(y,q);return (lx<=rx&&ly<=ry?s[0][rx][ry]-t[0][lx][ry]-t[1][rx][ly]+t[2][lx][ly]:0);
    }
    ll sub2(){ll res=1e18;for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) for(int p:{0,1,2,3}) for(int q:{0,1,2,3}) res=min(res,a[i].v+a[j].v+B-s[p][a[i].x][a[i].y]-s[q][a[j].x][a[j].y]+calc(i,j,p,q));return res;}
    ll sub3(){
        ll res=1e18;for(int i=1;i<=n;i++){
            for(int j=0;j<=X.size()+1;j++) pre[j]=suf[j]=1e18;
            for(int j=1;j<=n;j++) if(i^j){
                for(int p:{0,1}) pre[a[j].x]=min(pre[a[j].x],a[j].v-s[p][a[j].x][a[j].y]+calc(i,j,0,p));
                for(int p:{2,3}) suf[a[j].x]=min(suf[a[j].x],a[j].v-s[p][a[j].x][a[j].y]+calc(i,j,0,p));
            }for(int j=1;j<=X.size();j++) pre[j]=min(pre[j],pre[j-1]);
            for(int j=X.size();j;j--) suf[j]=min(suf[j],suf[j+1]);
            for(int j=0;j<=X.size();j++) res=min(res,a[i].v-s[0][a[i].x][a[i].y]+B+pre[j]+suf[j+1]);
            for(int j=0;j<=Y.size()+1;j++) pre[j]=suf[j]=1e18;
            for(int j=1;j<=n;j++) if(i^j){
                for(int p:{0,2}) pre[a[j].y]=min(pre[a[j].y],a[j].v-s[p][a[j].x][a[j].y]+calc(i,j,0,p));
                for(int p:{1,3}) suf[a[j].y]=min(suf[a[j].y],a[j].v-s[p][a[j].x][a[j].y]+calc(i,j,0,p));
            }for(int j=1;j<=Y.size();j++) pre[j]=min(pre[j],pre[j-1]);
            for(int j=Y.size();j;j--) suf[j]=min(suf[j],suf[j+1]);
            for(int j=0;j<=Y.size();j++) res=min(res,a[i].v-s[0][a[i].x][a[i].y]+B+pre[j]+suf[j+1]);
        }for(int i=1;i<=n;i++){
            Mi F,G,P,Q;
            auto upd=[&](int j,int p,Mi &V){ll v=a[j].v-s[p][a[j].x][a[j].y]+calc(i,j,0,p);Mi res;res.mi[0]={v,j};V=merge(V,res);};
    		auto U=[&](int j,ll v,Mi &V){Mi res;res.mi[0]={v,j};V=merge(V,res);};
            for(int j=1;j<=n;j++) if(i^j){
                if(a[j].x<=a[i].x) for(int p:{0,1}) upd(j,p,F);
                if(a[j].y<=a[i].y) for(int p:{0,2}) upd(j,p,G);
    			if(a[j].x>=a[i].x&&a[j].y>=a[i].y){
    				U(j,a[j].v-t[0][a[i].x][a[j].y],P);
    				U(j,a[j].v-t[1][a[j].x][a[i].y]+t[2][a[i].x][a[i].y],Q);
    			}
            }for(int x:{0,1}) for(int y:{0,1}){
    			if(F.mi[x][1]^G.mi[y][1]) res=min(res,a[i].v-s[0][a[i].x][a[i].y]+B+F.mi[x][0]+G.mi[y][0]);
    			if(P.mi[x][1]^Q.mi[y][1]) res=min(res,a[i].v-s[3][a[i].x][a[i].y]+B+P.mi[x][0]+Q.mi[x][0]);
    		}
        }for(int i=0;i<=X.size()+1;i++) for(int j=0;j<=Y.size()+1;j++) hyw[i][j]=Mi();
    	for(int i=1;i<=n;i++){Mi res;res.mi[0]={a[i].v,i};hyw[a[i].x][a[i].y]=merge(hyw[a[i].x][a[i].y],res);}
    	for(int i=1;i<=X.size();i++) for(int j=1;j<=Y.size();j++) hyw[i][j]=merge(hyw[i][j],hyw[i-1][j]),hyw[i][j]=merge(hyw[i][j],hyw[i][j-1]);
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i^j&&a[i].x<=a[j].x&&a[i].y>=a[j].y) for(int o:{0,1,2}) if(hyw[a[j].x][a[i].y].mi[o][1]^i&&hyw[a[j].x][a[i].y].mi[o][1]^j) res=min(res,a[i].v+a[j].v+hyw[a[j].x][a[i].y].mi[o][0]+t[2][a[i].x][a[j].y]);
        return res;
    }
    ll sub4(){if(n<4) return 1e18;sort(a+1,a+1+n,[&](Info x,Info y){return x.v<y.v;});ll res=0;for(int i=1;i<=4;i++) res+=a[i].v;return res;}
    void init(){
    	for(int i=1;i<=n;i++) a[i]=tmpa[i];for(int i=1;i<=m;i++) b[i]=tmpb[i];
    	X.clear();Y.clear();for(int i=1;i<=n;i++) X.push_back(a[i].x),Y.push_back(a[i].y);X.push_back(2e9);Y.push_back(2e9);
        sort(X.begin(),X.end());X.erase(unique(X.begin(),X.end()),X.end());sort(Y.begin(),Y.end());Y.erase(unique(Y.begin(),Y.end()),Y.end());
        for(int i=1;i<=n;i++) a[i].x=lower_bound(X.begin(),X.end(),a[i].x)-X.begin()+1,a[i].y=lower_bound(Y.begin(),Y.end(),a[i].y)-Y.begin()+1;
    	for(int i=0;i<=X.size()+1;i++) for(int j=0;j<=Y.size()+1;j++){for(int o:{0,1,2,3}) s[o][i][j]=0;for(int o:{0,1,2}) t[o][i][j]=0;}
        for(int i=1;i<=m;i++){
            int x=lower_bound(X.begin(),X.end(),b[i].x)-X.begin()+1,y=lower_bound(Y.begin(),Y.end(),b[i].y)-Y.begin()+1;
            s[0][x][y]+=b[i].v;
        }for(int i=1;i<=X.size();i++) for(int j=1;j<=Y.size();j++) s[0][i][j]+=s[0][i-1][j]+s[0][i][j-1]-s[0][i-1][j-1];
        for(int i=1;i<=m;i++){
            int x=lower_bound(X.begin(),X.end(),b[i].x)-X.begin()+1,y=upper_bound(Y.begin(),Y.end(),b[i].y)-Y.begin();
            s[1][x][y]+=b[i].v;
        }for(int i=1;i<=X.size();i++) for(int j=Y.size();j;j--) s[1][i][j]+=s[1][i-1][j]+s[1][i][j+1]-s[1][i-1][j+1];
        for(int i=1;i<=m;i++){
            int x=upper_bound(X.begin(),X.end(),b[i].x)-X.begin(),y=lower_bound(Y.begin(),Y.end(),b[i].y)-Y.begin()+1;
            s[2][x][y]+=b[i].v;
        }for(int i=X.size();i;i--) for(int j=1;j<=Y.size();j++) s[2][i][j]+=s[2][i+1][j]+s[2][i][j-1]-s[2][i+1][j-1];
        for(int i=1;i<=m;i++){
            int x=upper_bound(X.begin(),X.end(),b[i].x)-X.begin(),y=upper_bound(Y.begin(),Y.end(),b[i].y)-Y.begin();
            s[3][x][y]+=b[i].v;
        }for(int i=X.size();i;i--) for(int j=Y.size();j;j--) s[3][i][j]+=s[3][i+1][j]+s[3][i][j+1]-s[3][i+1][j+1];
        for(int i=1;i<=m;i++){
            int x=upper_bound(X.begin(),X.end(),b[i].x)-X.begin()+1,y=lower_bound(Y.begin(),Y.end(),b[i].y)-Y.begin()+1;
            t[0][x][y]+=b[i].v;
        }for(int i=1;i<=X.size();i++) for(int j=1;j<=Y.size();j++) t[0][i][j]+=t[0][i-1][j]+t[0][i][j-1]-t[0][i-1][j-1];
        for(int i=1;i<=m;i++){
            int x=lower_bound(X.begin(),X.end(),b[i].x)-X.begin()+1,y=upper_bound(Y.begin(),Y.end(),b[i].y)-Y.begin()+1;
            t[1][x][y]+=b[i].v;
        }for(int i=1;i<=X.size();i++) for(int j=1;j<=Y.size();j++) t[1][i][j]+=t[1][i-1][j]+t[1][i][j-1]-t[1][i-1][j-1];
        for(int i=1;i<=m;i++){
            int x=upper_bound(X.begin(),X.end(),b[i].x)-X.begin()+1,y=upper_bound(Y.begin(),Y.end(),b[i].y)-Y.begin()+1;
            t[2][x][y]+=b[i].v;
        }for(int i=1;i<=X.size();i++) for(int j=1;j<=Y.size();j++) t[2][i][j]+=t[2][i-1][j]+t[2][i][j-1]-t[2][i-1][j-1];
    }
    void rotate(){
    	for(int i=1;i<=n;i++) swap(tmpa[i].x,tmpa[i].y),tmpa[i].x=-tmpa[i].x;
    	for(int i=1;i<=m;i++) swap(tmpb[i].x,tmpb[i].y),tmpb[i].x=-tmpb[i].x;
    }
    signed main(){
        n=read();m=read();for(int i=1;i<=n;i++) a[i]=tmpa[i]={read(),read(),read()};for(int i=1;i<=m;i++) b[i]=tmpb[i]={read(),read(),read()},B+=b[i].v;
    	init();ll ans=min({B,sub1(),sub2(),sub3(),sub4()});rotate();init();ans=min(ans,sub3());rotate();init();ans=min(ans,sub3());rotate();init();ans=min(ans,sub3());cout<<ans;
        return 0;
    }
    
    • 1

    信息

    ID
    9600
    时间
    5000ms
    内存
    2048MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者