LYDSY模拟赛 escape

Description

给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上矩形的
行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2)。在移动的过程中你
当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下你最少要走多少步
才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d)那么它们的距
离为|a-c|+|b-d|

Input

第一行给出数字N,X,Y 
第二行给出x1,y1,x2,y2 
下面将有N行,给出N个敌人所在的坐标

Output

在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。

Sample Input

2 5 6
0 0 4 0
2 1
2 3

Sample Output

2 14
/*
①灌水法 by hzwer
②二维前缀和 by me
③并查集乱搞 by 某神犇
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<vector>
#define ll long long
#define x1 X1
#define y1 Y1
#define x2 X2
#define y2 Y2
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int ans1,ans2;
int head,tail;
int n,X,Y;
int x1,y1,x2,y2;
int mp[1005][1005];
int x[1000005],y[1000005],step[1000005];
bool vis[1005][1005];
int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1};
void pre()
{
    while(head!=tail)
    {
        int nx=x[head],ny=y[head];head++;
        for(int k=0;k<4;k++)
        {
            int tx=nx+xx[k],ty=ny+yy[k];
            if(tx>=X||ty>=Y||tx<0||ty<0||mp[tx][ty]!=-1)continue;
            mp[tx][ty]=mp[nx][ny]+1;
            x[tail]=tx;y[tail]=ty;tail++;
        }
    }
}
int bfs(int val)
{
    head=0;tail=1;
    if(x1==x2&&y1==y2)return 0;
    memset(vis,0,sizeof(vis));
    vis[x1][y1]=1;x[0]=x1;y[0]=y1;
    while(head!=tail)
    {
        int nx=x[head],ny=y[head],ns=step[head];head++;
        for(int k=0;k<4;k++)
        {
            int tx=nx+xx[k],ty=ny+yy[k];
            if(tx>=X||ty>=Y||tx<0||ty<0||mp[tx][ty]<val||vis[tx][ty])continue;
            vis[tx][ty]=1;
            if(tx==x2&&ty==y2)return ns+1;
            x[tail]=tx;y[tail]=ty;step[tail]=ns+1;tail++;
        }
    }
    return -1;
}
int main()
{
    //freopen("escape.in","r",stdin);
    //freopen("escape.out","w",stdout);
    memset(mp,-1,sizeof(mp));
    n=read();X=read();Y=read();
    x1=read();y1=read();x2=read();y2=read();
    for(int i=1;i<=n;i++)
    {
        int a=read(),b=read();
        mp[a][b]=0;
        x[tail]=a;y[tail]=b;tail++;
    }
    pre();
    int l=0,r=mp[x1][y1];
    while(l<=r)
    {
        int mid=(l+r)>>1;
        int t=bfs(mid);
        if(t==-1)r=mid-1;
        else l=mid+1,ans1=mid,ans2=t;
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn = 10050,inf = 987654;
inline int read(){
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>=‘0‘&&ch<=‘9‘)){if(ch==‘-‘)f=-1;ch=getchar();};
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+(ch-‘0‘);ch=getchar();};
    return x*f;
}
struct nd{
    int x;
    int y;
};
int p,n,m;
int ex[maxn],ey[maxn],xa,xb,ya,yb;
int flag,dis[1150][1150],vis[1050][1050];
short d[3100][3100],s[3100][3100];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
bool emy[3050][3050];
inline bool jud(int x,int y,int t){
    if(x < 0 || y < 0 || x >= m || y >= n) return false;
    if(t == 0) return true;
    t--;
    int tx=1005+x-y+t,ty=x+y+t,dx=1005+x-y-t,dy=x+y-t;
    if(ty>=n+m-1) ty = n+m-2;
    if(tx>=1005+m) tx = 1004+m;
    int tot = s[ty][tx];
    if(dy>0&&dx>1006-n) tot += s[dy-1][dx-1];
    if(dy>0) tot -= s[dy-1][tx];
    if(dx>1006-n) tot -= s[ty][dx-1];
    if(tot) return false;
    else return true;
}
bool check(int t){
    if(!jud(xa,ya,t)) return false;
    flag++;
    for(int i = 0;i <= n+10;i++){
        for(int j = 0;j <= m+10;j++){
            dis[i][j] = inf;
        }
    }
    nd now,nxt;
    now.x = xa;
    now.y = ya;
    queue<nd> q;
    q.push(now);
    dis[ya][xa] = 0;
    vis[ya][xa] = flag;
    while(!q.empty()){
        now = q.front();
        q.pop();
        //cout<<now.y<<" "<<now.x<<endl;
        for(int dr = 0;dr < 4;dr++){
            nxt.x = now.x + dx[dr];
            nxt.y = now.y + dy[dr];
            if(jud(nxt.x,nxt.y,t)&&vis[nxt.y][nxt.x] != flag){
                dis[nxt.y][nxt.x] = dis[now.y][now.x] + 1;
                vis[nxt.y][nxt.x] = flag;
                q.push(nxt);
                if(nxt.y == yb && nxt.x == xb) return true;
            }
        }
    }
    return false;
}
int main(){
    cin>>p>>m>>n>>xa>>ya>>xb>>yb;
    for(int i = 1;i <= p;i++){
        scanf("%d%d",&ex[i],&ey[i]);
        emy[ex[i]+ey[i]][1005+ex[i]-ey[i]] = true;
    }
    for(int i = 0;i < n + m - 1;i++){
        for(int j = 1006-n;j < 1005+m;j++){
            if(emy[i][j]) d[i][j] = d[i][j-1] + 1;
            else d[i][j] = d[i][j-1];
        }
    }
    for(int i = 0;i < n + m - 1;i++){
        for(int j = 1006-n;j < 1005+m;j++){
            if(!i) s[i][j] = d[i][j];
            else s[i][j] = s[i-1][j] + d[i][j];
        }
    }
    int l = 0,r = n + m,mid,ans1,ans2;
    while(l <= r){
        mid = (l + r) >> 1;
        if(check(mid)){
            ans1 = mid;
            ans2 = dis[yb][xb];
            l = mid + 1;
        }else{
            r = mid - 1;
        }
    }
    cout<<ans1<<" "<<ans2;
    return 0;
}

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

const int N=10000+5;
const int X=1000+5, Y=1000+5;
const int pace[4][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

int n, sz_x, sz_y;

struct Point {
    int x, y;
    inline Point(int _x=0, int _y=0): x(_x), y(_y) {}
    inline Point walk(int k) {
        return Point(x+pace[k][0], y+pace[k][1]);
    }
};

Point S, D;

int dis_enemy[X][Y];

inline void read_general() {
    scanf("%d%d%d", &n, &sz_x, &sz_y);
    scanf("%d%d%d%d", &S.x, &S.y, &D.x, &D.y);
}

inline void read_enemy_and_process_dis() {
    memset(dis_enemy, 0x3f, sizeof(dis_enemy));
    queue<Point> q;
    for(int i=1; i<=n; ++i) {
        Point E; scanf("%d%d", &E.x, &E.y);
        dis_enemy[E.x][E.y]=0;
        q.push(E);
    }
    while(!q.empty()) {
        Point U=q.front(); q.pop();
        for(int k=0; k<4; ++k) {
            Point V=U.walk(k);
            if(V.x<0 || V.x>=sz_x || V.y<0 || V.y>=sz_y ||
                dis_enemy[V.x][V.y]<0x3f3f3f00) continue;
            dis_enemy[V.x][V.y]=dis_enemy[U.x][U.y]+1;
            q.push(V);
        }
    }
}

int dis_s[X][Y];

inline int calc_dist(int mid) {
    memset(dis_s, 0x3f, sizeof(dis_s));
    queue<Point> q;
    if(dis_enemy[S.x][S.y]>=mid) {
        q.push(S);
        dis_s[S.x][S.y]=0;
    }
    while(!q.empty()) {
        Point U=q.front(); q.pop();
        for(int k=0; k<4; ++k) {
            Point V=U.walk(k);
            if(V.x<0 || V.x>=sz_x || V.y<0 || V.y>=sz_y ||
                dis_enemy[V.x][V.y]<mid ||
                dis_s[V.x][V.y]<0x3f3f3f00) continue;
            dis_s[V.x][V.y]=dis_s[U.x][U.y]+1;
            q.push(V);
        }
    }
    return dis_s[D.x][D.y];
}

int main() {
    read_general();
    read_enemy_and_process_dis();
    int l=0, r=100000;
    while(l<r-1) {
        int mid=(l+r)>>1;
        if(calc_dist(mid)<0x3f3f3f00) l=mid; else r=mid;
    }
    printf("%d %d\n", l, calc_dist(l));
    return 0;
}
 
/*
①灌水法 by hzwer
②二维前缀和 by me
③并查集乱搞 by 某神犇
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<vector>
#define ll long long
#define x1 X1
#define y1 Y1
#define x2 X2
#define y2 Y2
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int ans1,ans2;
int head,tail;
int n,X,Y;
int x1,y1,x2,y2;
int mp[1005][1005];
int x[1000005],y[1000005],step[1000005];
bool vis[1005][1005];
int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1};
void pre()
{
    while(head!=tail)
    {
        int nx=x[head],ny=y[head];head++;
        for(int k=0;k<4;k++)
        {
            int tx=nx+xx[k],ty=ny+yy[k];
            if(tx>=X||ty>=Y||tx<0||ty<0||mp[tx][ty]!=-1)continue;
            mp[tx][ty]=mp[nx][ny]+1;
            x[tail]=tx;y[tail]=ty;tail++;
        }
    }
}
int bfs(int val)
{
    head=0;tail=1;
    if(x1==x2&&y1==y2)return 0;
    memset(vis,0,sizeof(vis));
    vis[x1][y1]=1;x[0]=x1;y[0]=y1;
    while(head!=tail)
    {
        int nx=x[head],ny=y[head],ns=step[head];head++;
        for(int k=0;k<4;k++)
        {
            int tx=nx+xx[k],ty=ny+yy[k];
            if(tx>=X||ty>=Y||tx<0||ty<0||mp[tx][ty]<val||vis[tx][ty])continue;
            vis[tx][ty]=1;
            if(tx==x2&&ty==y2)return ns+1;
            x[tail]=tx;y[tail]=ty;step[tail]=ns+1;tail++;
        }
    }
    return -1;
}
int main()
{
    //freopen("escape.in","r",stdin);
    //freopen("escape.out","w",stdout);
    memset(mp,-1,sizeof(mp));
    n=read();X=read();Y=read();
    x1=read();y1=read();x2=read();y2=read();
    for(int i=1;i<=n;i++)
    {
        int a=read(),b=read();
        mp[a][b]=0;
        x[tail]=a;y[tail]=b;tail++;
    }
    pre();
    int l=0,r=mp[x1][y1];
    while(l<=r)
    {
        int mid=(l+r)>>1;
        int t=bfs(mid);
        if(t==-1)r=mid-1;
        else l=mid+1,ans1=mid,ans2=t;
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn = 10050,inf = 987654;
inline int read(){
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>=‘0‘&&ch<=‘9‘)){if(ch==‘-‘)f=-1;ch=getchar();};
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+(ch-‘0‘);ch=getchar();};
    return x*f;
}
struct nd{
    int x;
    int y;
};
int p,n,m;
int ex[maxn],ey[maxn],xa,xb,ya,yb;
int flag,dis[1150][1150],vis[1050][1050];
short d[3100][3100],s[3100][3100];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
bool emy[3050][3050];
inline bool jud(int x,int y,int t){
    if(x < 0 || y < 0 || x >= m || y >= n) return false;
    if(t == 0) return true;
    t--;
    int tx=1005+x-y+t,ty=x+y+t,dx=1005+x-y-t,dy=x+y-t;
    if(ty>=n+m-1) ty = n+m-2;
    if(tx>=1005+m) tx = 1004+m;
    int tot = s[ty][tx];
    if(dy>0&&dx>1006-n) tot += s[dy-1][dx-1];
    if(dy>0) tot -= s[dy-1][tx];
    if(dx>1006-n) tot -= s[ty][dx-1];
    if(tot) return false;
    else return true;
}
bool check(int t){
    if(!jud(xa,ya,t)) return false;
    flag++;
    for(int i = 0;i <= n+10;i++){
        for(int j = 0;j <= m+10;j++){
            dis[i][j] = inf;
        }
    }
    nd now,nxt;
    now.x = xa;
    now.y = ya;
    queue<nd> q;
    q.push(now);
    dis[ya][xa] = 0;
    vis[ya][xa] = flag;
    while(!q.empty()){
        now = q.front();
        q.pop();
        //cout<<now.y<<" "<<now.x<<endl;
        for(int dr = 0;dr < 4;dr++){
            nxt.x = now.x + dx[dr];
            nxt.y = now.y + dy[dr];
            if(jud(nxt.x,nxt.y,t)&&vis[nxt.y][nxt.x] != flag){
                dis[nxt.y][nxt.x] = dis[now.y][now.x] + 1;
                vis[nxt.y][nxt.x] = flag;
                q.push(nxt);
                if(nxt.y == yb && nxt.x == xb) return true;
            }
        }
    }
    return false;
}
int main(){
    cin>>p>>m>>n>>xa>>ya>>xb>>yb;
    for(int i = 1;i <= p;i++){
        scanf("%d%d",&ex[i],&ey[i]);
        emy[ex[i]+ey[i]][1005+ex[i]-ey[i]] = true;
    }
    for(int i = 0;i < n + m - 1;i++){
        for(int j = 1006-n;j < 1005+m;j++){
            if(emy[i][j]) d[i][j] = d[i][j-1] + 1;
            else d[i][j] = d[i][j-1];
        }
    }
    for(int i = 0;i < n + m - 1;i++){
        for(int j = 1006-n;j < 1005+m;j++){
            if(!i) s[i][j] = d[i][j];
            else s[i][j] = s[i-1][j] + d[i][j];
        }
    }
    int l = 0,r = n + m,mid,ans1,ans2;
    while(l <= r){
        mid = (l + r) >> 1;
        if(check(mid)){
            ans1 = mid;
            ans2 = dis[yb][xb];
            l = mid + 1;
        }else{
            r = mid - 1;
        }
    }
    cout<<ans1<<" "<<ans2;
    return 0;
}

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

const int N=10000+5;
const int X=1000+5, Y=1000+5;
const int pace[4][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

int n, sz_x, sz_y;

struct Point {
    int x, y;
    inline Point(int _x=0, int _y=0): x(_x), y(_y) {}
    inline Point walk(int k) {
        return Point(x+pace[k][0], y+pace[k][1]);
    }
};

Point S, D;

int dis_enemy[X][Y];

inline void read_general() {
    scanf("%d%d%d", &n, &sz_x, &sz_y);
    scanf("%d%d%d%d", &S.x, &S.y, &D.x, &D.y);
}

inline void read_enemy_and_process_dis() {
    memset(dis_enemy, 0x3f, sizeof(dis_enemy));
    queue<Point> q;
    for(int i=1; i<=n; ++i) {
        Point E; scanf("%d%d", &E.x, &E.y);
        dis_enemy[E.x][E.y]=0;
        q.push(E);
    }
    while(!q.empty()) {
        Point U=q.front(); q.pop();
        for(int k=0; k<4; ++k) {
            Point V=U.walk(k);
            if(V.x<0 || V.x>=sz_x || V.y<0 || V.y>=sz_y ||
                dis_enemy[V.x][V.y]<0x3f3f3f00) continue;
            dis_enemy[V.x][V.y]=dis_enemy[U.x][U.y]+1;
            q.push(V);
        }
    }
}

int dis_s[X][Y];

inline int calc_dist(int mid) {
    memset(dis_s, 0x3f, sizeof(dis_s));
    queue<Point> q;
    if(dis_enemy[S.x][S.y]>=mid) {
        q.push(S);
        dis_s[S.x][S.y]=0;
    }
    while(!q.empty()) {
        Point U=q.front(); q.pop();
        for(int k=0; k<4; ++k) {
            Point V=U.walk(k);
            if(V.x<0 || V.x>=sz_x || V.y<0 || V.y>=sz_y ||
                dis_enemy[V.x][V.y]<mid ||
                dis_s[V.x][V.y]<0x3f3f3f00) continue;
            dis_s[V.x][V.y]=dis_s[U.x][U.y]+1;
            q.push(V);
        }
    }
    return dis_s[D.x][D.y];
}

int main() {
    read_general();
    read_enemy_and_process_dis();
    int l=0, r=100000;
    while(l<r-1) {
        int mid=(l+r)>>1;
        if(calc_dist(mid)<0x3f3f3f00) l=mid; else r=mid;
    }
    printf("%d %d\n", l, calc_dist(l));
    return 0;
}
 
时间: 2024-10-13 10:17:34

LYDSY模拟赛 escape的相关文章

LYDSY模拟赛day3 序列

NOIP不考可持久,弃坑

LYDSY模拟赛day1 Walk

/* 依旧考虑新增 2^20 个点. i 只需要向 i 去掉某一位的 1 的点连边. 这样一来图的边数就被压缩到了 20 · 2^20 + 2n + m,然后 BFS 求出 1 到每个点的最短路即可. 时间复杂度 O(20 · 2^20 + n + m) */ #include<cstdio> const int N=1300000,M=700010; int n,m,i,x,y,cnt,g0[N],g1[N],v[M],nxt[M],ed,h,t,q[N],d[N]; void add(in

LYDSY模拟赛day2 Dash Speed

/* 弃坑 */ #include<cstdio> #include<algorithm> using namespace std; const int N=70010,M=N*20; int n,m,i,g[N],v[N<<1],nxt[N<<1],ed,cur,ans[N]; int size[N],f[N],d[N],son[N],top[N]; int fa[N],dep[N],A[N],B[N]; int G[262150],V[M],W[M],N

LYDSY模拟赛day2 Market

/* orz claris,这个题的解法非常巧妙,首先是时间问题,其实这个问题只要离线处理一下就可以了,把物品和询问都按照时间排序,然后看一下能不能满足.然后,因为容量<=10^9,显然是不可能开一个这么大的数组,而且这么大一个容量,价值又很小,我们可以考虑用二分解决 对每个询问二分答案,需要判定用容量为 M 的背包是否可 以装下 mid 的价值. 设 fi 表示装了 i 价值所需的最小容量,gi 表示 min(fi,fi+1,fi+2,……). 那么只需要检查 gmid 是否不超过 M 即可.

LYDSY模拟赛day2 Divisors

/* 注意分解质因数,如果i是,那么n/i也是,这样就可以解决分解质因数的时间问题了 当 k ≥ 1 时,只有这些数的约数才会对答案产生贡献. 求出 m 个数的所有不超过 n 的约数,去重后统计即可. 求出 k = 1 到 m 的所有答案后,剩下的数字个数就是 k = 0 的答案. 时间复杂度 O(m2√a) */ #include<cstdio> #include<algorithm> const int N=205; int n,m,i,a[N],cnt,b[1000000],

LYDSY模拟赛day3 平均数

[ 问题描述]有一天, 小 A 得到了一个长度为 n 的序列.他把这个序列的所有连续子序列都列了出来, 并对每一个子序列都求了其平均值, 然后他把这些平均值写在纸上, 并对它们进行排序,最后他报出了第 k 小的平均值.你要做的就是模仿他的过程.[ 输入格式]第一行两个整数 n,k, 意义如题中所述.第二行 n 个正整数, 即为小 A 得到的序列.[ 输出格式]一行一个实数, 表示第 k 小的平均值, 保留到小数点后 4 位.[ 样例输入输出] ave.in ave.out 6 103 5 4 6

20180610模拟赛T1——脱离地牢

Description 在一个神秘的国度里,年轻的王子Paris与美丽的公主Helen在一起过着幸福的生活.他们都随身带有一块带磁性的阴阳魔法石,身居地狱的魔王Satan早就想着得到这两块石头了,只要把它们溶化,Satan就能吸收其精华大增自己的魔力.于是有一天他趁二人不留意,把他们带到了自己的地牢,分别困在了不同的地方.然后Satan念起了咒语,准备炼狱,界时二人都将葬身于这地牢里. 危险!Paris与Helen都知道了Satan的意图,他们要怎样才能打败魔王,脱离地牢呢?Paris想起了父王

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=