10.3 CSP B組模擬賽

 

寫在前面:

  至於10.3號的模擬爲何今天寫。。。。這種事情不是很顯而易見嘛。node

  我但是養鴿大戶QAQios

 


  其實這兩天的題都還好,不算難。ide

T1 長方形

  考試考結論以及數學對我來講最不友好了啊QAQ優化

  雞腿想到了一個很高(sha)明(bi)的問題,在 N 條水平線與 M 條豎直線構成的網格中,放 K 枚石子,每一個石子都只能放在網格的交叉點上。問在最優的擺放方式下,最多能找到多少四邊平行於座標軸的長方形,它的四個角上都剛好放着一枚石子。spa

  對於大家來講,這種結論題簡直顯然。code

  可是我打完T2,T3以後一個多小時全在搞這個題,最後交了個暴力QAQblog

  結論:

    能把點堆在一塊兒就堆在一塊兒。多出來的位置再單獨計算。數學

  那麼這題咱們只須要枚舉能圍城的邊長,而後處理多出來的部分,就完事了。string

 代碼it

  數學菜雞跟着題解改了小一個小時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+

相關文章
相關標籤/搜索