10.3 CSP B组模拟赛

 

写在前面:

  至于10.3号的模拟为什么今天写。。。。这种事情不是很显而易见嘛。

  我可是养鸽大户QAQ


  其实这两天的题都还好,不算难。

T1 长方形

  考试考结论以及数学对我来说最不友好了啊QAQ

  鸡腿想到了一个很高(sha)明(bi)的问题,在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。

  对于你们来说,这种结论题简直显然。

  但是我打完T2,T3之后一个多小时全在搞这个题,最后交了个暴力QAQ

  结论:

    能把点堆在一起就堆在一起。多出来的位置再单独计算。

  那么这题我们只需要枚举能围城的边长,然后处理多出来的部分,就完事了。

 代码

  数学菜鸡跟着题解改了小一个小时QAQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int n,m,k,ans=0;

int ad(int x,int y,int i) {
    return x*(x-1)/2*i*(i-1)/2+y*(y-1)/2*x;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=2;i<=m;i++) {
        int x=k/i,y=k%i;
        if(x>n)
            continue;
        if(x==n&&y) 
            continue;
        ans=max(ans,ad(x,y,i));
    }
    for(int i=2;i<=n;i++) {
        int x=k/i,y=k%i;
        if(x>m)
            continue;
        if(x==m&&y) 
            continue;
        ans=max(ans,ad(x,y,i));
    }
    cout<<ans<<endl;;
    return 0;
}
T1 Code

T2 连通块

  这题简直友好啊友好。

  Alice为了刁难你,拆掉编号从lr的边,当然你需要做的事情就是求连通块的个数。

  不记得在哪次集训的时候讲过的一种思想了,还好还记得。

  运用类似分块的思想【可能是我太喜欢分块了QAQ

  把图中的点看作3部分:

    1. l前

    2. r后

    3. l~r

  那么如果要是想要求出 除了l~r 的信息,那不就是只求第一和第三部分的结果吗?

  很显然,我们可以很轻松的通过预处理的方法求出任意位置x的1~x和x~n的结果。

  询问的答案就是使用预处理的答案,fa[l-1]与fa[r+1]的值进行合并。

  那么显然这就是一个二维并查集维护连通块个数的问题了。

 代码来啦

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int n,m,k;
struct ss{
    int l,r;
}d[100007];
int a[510],fa[10007][510],ba[10007][510]; 

int fi_fa(int id,int x) {
    if(fa[id][x]==x)
        return x;
    return fa[id][x]=fi_fa(id,fa[id][x]);
}

int fi_ba(int id,int x) {
    if(ba[id][x]==x)
        return x;
    return ba[id][x]=fi_ba(id,ba[id][x]);
}

int fi_a(int x) {
    if(a[x]==x)
        return x;
    return a[x]=fi_a(a[x]);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) 
        scanf("%d%d",&d[i].l,&d[i].r);
    for(int i=1;i<=n;i++) {
        fa[0][i]=i;
        ba[m+1][i]=i;
    }
    for(int i=1;i<=m;i++) {
        memcpy(fa[i],fa[i-1],sizeof fa[i]);
        int col_x=fi_fa(i,d[i].l);
        int col_y=fi_fa(i,d[i].r);
        if(col_x!=col_y) 
            fa[i][col_x]=col_y;
    }
    for(int i=m;i>=1;i--) {
        memcpy(ba[i],ba[i+1],sizeof ba[i]);
        int col_x=fi_ba(i,d[i].l);
        int col_y=fi_ba(i,d[i].r);
        if(col_x!=col_y)
            ba[i][col_x]=col_y;
    }
    scanf("%d",&k);
    while(k--) {
        int l,r;
        scanf("%d%d",&l,&r);
        memcpy(a,fa[l-1],sizeof a);
        for(int i=1;i<=n;i++) {
            int col_x=fi_a(a[i]);
            int col_y=fi_a(ba[r+1][i]);
            if(col_x!=col_y) 
                a[col_x]=col_y;
        }
        int ans=0;
        for(int i=1;i<=n;i++) 
            if(a[i]==i)
                ans++;
        cout<<ans<<endl;
    }
    return 0;
}
T1 Code

T3 山峰

  搞什么啊,模拟赛就这样考一道小搜索真的好吗?

  一个高度为h地点被称作d-山峰,只有满足从这里出发,在不经过小于等于h-d的地点的前提下无法达到比它更高的地方。

  简洁易懂的语言加上500的数据范围,我仿佛在做普及组QAQ

  所以这题就是个时间tag优化bfs。

具体细节看代码吧 ?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;

int dx[5]={0,0,1,0,-1};
int dy[5]={0,1,0,-1,0};
int n,m,d,tim,maxn;
int mp[507][507],vis[507][507];
bool flag;
struct node{
    int x,y;
};

void bfs(int x,int y) {
    queue<node> q;
    q.push((node){x,y});
    int high=mp[x][y]-d;
    vis[x][y]=++tim;
    while(!q.empty()) {
        node nw=q.front();
        q.pop();
        for(int i=1;i<=4;i++) {
            int nwx=nw.x+dx[i];
            int nwy=nw.y+dy[i];
            if(nwx<1||nwx>n||nwy<1||nwy>m)
                continue;
            if(mp[nwx][nwy]<=high||vis[nwx][nwy]==tim) 
                continue;
            if(mp[nwx][nwy]>mp[x][y]) {
                flag=1;
                return;
            }
            vis[nwx][nwy]=tim;
            q.push((node){nwx,nwy});
        }
    }
    return;
}

int main()
{
    scanf("%d%d%d",&n,&m,&d);
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            scanf("%d",&mp[i][j]);
            maxn=max(maxn,mp[i][j]);
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(mp[i][j]==maxn) 
                continue;
            bfs(i,j);
            if(flag) {
                ans++;
                flag=0;
            }
        }
    }
    cout<<n*m-ans<<endl;
    return 0;
}
T3 Code

总结  

  最后总结一下,其实B组的题还是蛮水的QAQ

  期待下次可以200+

猜你喜欢

转载自www.cnblogs.com/qxyzili--24/p/11624266.html