7.23模拟赛

T1.matrix

多次询问A*B的区间和

不考虑naive地乘出来,画个图就能发现,总是A的一些列,乘以B的一些行。

维护多行多列的前缀和,就可以做了

时间复杂度O(nm)

#include<iostream>
#include<cstdio>
#define R register
using namespace std;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN=2048;

int n,m;
int a[MAXN*MAXN],b[MAXN*MAXN];
long long sa[MAXN*MAXN],sb[MAXN*MAXN];

int main(){
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    n=rd();m=rd();
    for(R int i=1;i<=n;i++)
        for(R int j=1;j<=n;j++)
            a[(i<<11)+j]=rd();
    for(R int i=1;i<=n;i++)
        for(R int j=1;j<=n;j++)
            b[(i<<11)+j]=rd();
    for(R int i=1;i<=n;i++){
        for(R int j=1;j<=n;j++){
            sa[(i<<11)+j]=sa[(i<<11)+j-1]+a[(j<<11)+i];//i row j line
            sb[(i<<11)+j]=sb[(i<<11)+j-1]+b[(i<<11)+j];//i line j row
        }
    }
    int x,y,u,v;
    long long ans=0;
    for(R int i=1;i<=m;i++){
        ans=0;
        x=rd();y=rd();u=rd();v=rd();
        if(x>u)swap(x,u);if(y>v)swap(y,v);
        for(int j=1;j<=n;j++)
            ans+=1ll*(sa[(j<<11)+u]-sa[(j<<11)+x-1])*1ll*(sb[(j<<11)+v]-sb[(j<<11)+y-1]);
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

T2.tower

写了模拟退火,初始状态集合设的二元组(x,y),x∈{所有x},y∈{所有y},发现跑的很稳定,很快

原因是,答案就一定在这些点里啊!

如果一个点的横纵坐标都不曾出现的话,那它就不和任何一个点在同一行、列,这样的情况是不优秀的。

而本题求的是曼哈顿距离,可以证明,这些初始集合里的这些二元组,一定不是劣解。

暴力跑一跑就可以了。(迷途知返)

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#define id(x,y) ((x)*(n+1)+(y))
#define R register
using namespace std;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN=64;
//const double COOL=0.98;
//const double eps=1e-6;

struct Point{
    int x,y;
    Point(int u=0,int v=0){x=u;y=v;}
}po[MAXN];
inline int dis(int x,int y,int u,int v){
    return abs(x-u)+abs(y-v);
}

int n;
int xs[MAXN],ys[MAXN],totx,toty;
vector<int> ans[MAXN*MAXN];
int sum[MAXN][MAXN][MAXN];

int main(){
    freopen("tower.in","r",stdin);
    freopen("tower.out","w",stdout);
    n=rd();
    int x,y,u,v;
    for(R int i=1;i<=n;i++){
        xs[i] = po[i].x = rd();
        ys[i] = po[i].y = rd();
    }
    sort(xs+1,xs+1+n);
    sort(ys+1,ys+1+n);
    totx=unique(xs+1,xs+1+n)-xs-1;
    toty=unique(ys+1,ys+1+n)-ys-1;
    for(R int i=1;i<=totx;i++){
        for(R int j=1;j<=toty;j++){
            x=xs[i];y=ys[j];v=id(i,j);
            for(R int k=1;k<=n;k++){
                ans[v].push_back(dis(x,y,po[k].x,po[k].y));
            }
            sort(ans[v].begin(),ans[v].end());
        }
    }
    for(R int k=1;k<=n;k++){
        for(R int i=1;i<=totx;i++){
            for(R int j=1;j<=toty;j++){
                sum[i][j][k]=sum[i][j][k-1]+ans[id(i,j)][k-1];
            }
        }
    }
    for(R int k=1;k<=n;k++){
        int mn=1<<30;
        for(R int i=1;i<=totx;i++){
            for(R int j=1;j<=toty;j++){
                mn=min(mn,sum[i][j][k]);
            }
        }
        printf("%d\n",mn);
    }
    return 0;
}
View Code

 

posted @ 2018-07-23 16:34  GhostCai  阅读(218)  评论(1编辑  收藏  举报