GDKOI2021 PJ D1 题解

这个普及比普及水多了。(雾)

题目水到我 9:44 写完又对拍到 11:00 然后发现自己差劲的代码能力一遍AK?(并没有)

所以总结就不写了

考场本来有 Sublime ,结果想配一下自动补全的时候 C++ 包莫名其妙没了,于是只能当记事本用。

本来用的 fread 快读,但是发现数据后都没有回车 fread 会双倍末尾,于是换成了 getchar

这场比赛因为我清奇的脑回路变成了并查集专题。

T1 map

模拟水题。

#include<cstdio>
using namespace std;
int n,a[2010][2010],r[2010],c[2010],x=1,y=1,ox,oy;
template<typename T>void read(T &x){
    char c=getchar();
    for(;c<33;c=getchar());
    for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
int main(){
    freopen("map.in","r",stdin);
    freopen("map.out","w",stdout);
    read(n);
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            read(a[i][j]);
        }
    }
    for(int i=2;i<n;++i){
        r[i]=a[n][1];
        c[i]=a[1][n];
        for(int j=2;j<=n;++j){
            r[i]^=a[i][j]^a[n][j];
            c[i]^=a[j][i]^a[j][n];
        }
    }
    for(int i=2;i<n;++i){
        if(r[i]!=a[i][1]){
            x=i;
            ++ox;
        }
        if(c[i]!=a[1][i]){
            y=i;
            ++oy;
        }
    }
    if(a[1][1]==1){
        printf("1 1");  //然现在发现并不需要
    }else{
        printf("%d %d",ox>1?n:x,oy>1?n:y);
    }
    fclose(stdin);
    fclose(stdout);
    return(0);
}

T2 water

全场最有质量的题……?

是 water !

暗示我们比赛很水

然后身边一群人写 (nlog ^2n) ,然后 (nlog n) 的方法也很神奇,甚至 Splay 、甚至 ST 表、甚至权值线段树……甚至再套二分……?反正我写的并查集。


首先如果水越加越高,那么就会不断的使有水的区间变大。

所以直接对询问由小到大排序,记录区间的左右端点,暴力拓展,用并查集合并即可。

随便写写跑得飞快,然后写完 T4 把 T4 的 sz 数组 copy 了过来搞了个按秩合并。

#include<cstdio>
#include<algorithm>
#define N 200010
using namespace std;
int n,m,c[N],sz[N];
long long ans[N],a[N],s[N],l[N],r[N];
struct ques{
    int x,y,num;
}q[N];
template<typename T>void read(T &x){
    char c=getchar();
    for(;c<33;c=getchar());
    for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
bool cmp(ques a,ques b){
    return(a.y<b.y);
}
int root(int x){
    if(c[x]){
        sz[c[x]]+=sz[x];
        sz[x]=0;
        return(c[x]=root(c[x]));
    }
    return(x);
}
int uni(int x,int y){
    x=root(x);y=root(y);
    if(sz[x]<sz[y]){
        swap(x,y);
    }
    if(x!=y){
        c[y]=x;
        sz[x]+=sz[y];
        sz[y]=0;
        l[x]=min(l[x],l[y]);
        r[x]=max(r[x],r[y]);
    }
    return(x);
}
int main(){
    freopen("water.in","r",stdin);
    freopen("water.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;++i){
        read(a[i]);
        s[i]=s[i-1]+a[i];
        l[i]=r[i]=i;
        sz[i]=1;
    }
    for(int i=1;i<=m;++i){
        read(q[i].x);read(q[i].y);q[i].num=i;
    }
    sort(q+1,q+1+m,cmp);
    for(int i=1;i<=m;++i){
        q[i].x=root(q[i].x);
        for(;a[l[q[i].x]-1]<q[i].y&&l[q[i].x]>1;q[i].x=uni(l[q[i].x]-1,q[i].x));
        for(;a[r[q[i].x]+1]<q[i].y&&r[q[i].x]<n;q[i].x=uni(r[q[i].x]+1,q[i].x));
        ans[q[i].num]=(r[q[i].x]-l[q[i].x]+1)*q[i].y-s[r[q[i].x]]+s[l[q[i].x]-1];
    }
    for(int i=1;i<=m;++i){
        printf("%lld
",ans[i]);
    }
    fclose(stdin);
    fclose(stdout);
    return(0);
}

T3 match

甚至比 T1 好写,贪心显然。

然后死于数组没开大。

#include<cstdio>
#include<algorithm>
using namespace std;
int n,l,r,a[100010],ans;  //我谔谔极了
//int n,l,r,a[1000010],ans;
template<typename T>void read(T &x){
    char c=getchar();
    for(;c<33;c=getchar());
    for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
int main(){
    freopen("match.in","r",stdin);
    freopen("match.out","w",stdout);
    read(n);read(l);read(r);
    for(int i=1;i<=n;++i){
        read(a[i]);
    }
    sort(a+1,a+n+1);
    for(int x=1,y=n;x<=y;){
        if(x==y){
            ++ans;
            break;
        }else if(a[x]+a[y]<l){
            ++x;
            ++ans;
        }else if(a[x]+a[y]>r){
            --y;
            ++ans;
        }else{
            ++x;
            --y;
        }
    }
    printf("%d",ans);
    fclose(stdin);
    fclose(stdout);
    return(0);
}

T4 travel

考场上屡次打成 tarvel 了解一下?

首先就是,这道题是原题: USACO2018JanGold P1. MooTube

除了多了若干条边以外并没有任何区别。

离线排序并查集。

就跟T2一样

#include<cstdio>
#include<algorithm>
#define N 200010
using namespace std;
int n,m,k,s[N],sz[N],ans[N];
struct edge{
    int x,y,c;
}e[N<<3],q[N<<3];
template<typename T>void read(T &x){
    char c=getchar();
    for(;c<33;c=getchar());
    for(x=0;47<c&&c<58;x=(x<<3)+(x<<1)+(c^48),c=getchar());
}
bool cmp(edge a,edge b){
    return(a.c<b.c);
}
void pushup(int x){
    sz[s[x]]+=sz[x];
    sz[x]=0;
}
int root(int x){
    if(s[x]){
        pushup(x);
        return(s[x]=root(s[x]));
    }
    return(x);
}
int uni(int x,int y){
    x=root(x);y=root(y);
    if(sz[x]<sz[y]){
        swap(x,y);
    }
    if(x!=y){
        s[y]=x;
        pushup(y);
    }
    return(x);
}
int main(){
    freopen("travel.in","r",stdin);
    freopen("travel.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;++i){
        sz[i]=1;
    }
    for(int i=0;i<m;++i){
        read(e[i].x);read(e[i].y);read(e[i].c);
    }
    read(k);
    for(int i=0;i<k;++i){
        read(q[i].x);read(q[i].c);q[i].y=i;
    }
    sort(e,e+m,cmp);
    sort(q,q+k,cmp);
    for(int i=0,j=0;i<k;++i){
        for(;j<=m&&e[j].c<=q[i].c;uni(e[j].x,e[j].y),++j);
        ans[q[i].y]=sz[root(q[i].x)];
    }
    for(int i=0;i<k;++i){
        printf("%d
",ans[i]);
    }
    fclose(stdin);
    fclose(stdout);
    return(0);
}
原文地址:https://www.cnblogs.com/groundwater/p/14332383.html