AtCoder赛记

(持续更新)

NIKKEI Programming Contest 2019-2

A:

送分。

#include<cstdio>
int main(){
    int n;
    scanf("%d",&n);
    printf("%d\n",n-1>>1);
    return 0;
}
View Code

B:

想象对树分层即可。

#include<cstdio>
typedef long long ll;
const int mod=998244353;
int cnt[100050];
inline int fp(int a,int p){
    int s=1;
    while(p){
        if(p&1)s=(ll)s*a%mod;
        a=(ll)a*a%mod;
        p>>=1;
    }
    return s;
}
int main(){
    int n,i,x,maxn=0,ans=1;
    scanf("%d",&n);
    for(i=0;i<n;++i){
        scanf("%d",&x);
        if(!i&&x){
            puts("0");
            return 0;
        }
        if(x>maxn)maxn=x;
        ++cnt[x];
    }
    if(cnt[0]!=1){
        puts("0");
        return 0;
    }
    for(i=2;i<=maxn;++i)ans=(ll)ans*fp(cnt[i-1],cnt[i])%mod;
    printf("%d\n",ans);
    return 0;
}
View Code

C:
对a,b排序,若存在$a_i>b_i$,则答案为No。若存在$a_{i+1}\le b_i$,则为Yes(因为给a排序最多只需要n-1次交换,现在可以少交换1次)。

否则,检查是否一定需要n-1次交换,这个可以通过检查置换循环节实现。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100050;
struct node{
    int a,b;
}a[N];
int r[N];
inline bool cmp1(const node &a,const node &b){return a.b<b.b;}
inline bool cmp2(int x,int y){return a[x].a<a[y].a;}
int main(){
    int n,i,p,tot=1;
    scanf("%d",&n);
    for(i=1;i<=n;++i){scanf("%d",&a[i].a);r[i]=i;}
    for(i=1;i<=n;++i)scanf("%d",&a[i].b);
    sort(a+1,a+n+1,cmp1);sort(r+1,r+n+1,cmp2);
    for(i=1;i<=n;++i)if(a[r[i]].a>a[i].b){
        puts("No");
        return 0;
    }
    for(i=1;i<n;++i)if(a[r[i+1]].a<=a[i].b){
        puts("Yes");
        return 0;
    }
    for(p=r[1];p!=1;p=r[p])++tot;
    puts(tot==n?"No":"Yes");
    return 0;
}
View Code

D:

线段树优化建图板子题。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int N=100050;
int G[N*10],to[N*100],w[N*100],nxt[N*100],sz=0,tot,id1[N<<2],id2[N<<2],x,y,p,c;
ll d[N*10];
struct node{
    int p;
    ll d;
    node(){}
    node(int p,ll d):p(p),d(d){}
    inline bool operator <(const node &b)const{return d>b.d;}
};
priority_queue<node> Q;
inline void adde(int u,int v,int c){
    to[++sz]=v;w[sz]=c;nxt[sz]=G[u];G[u]=sz;
}
void build(int o,int L,int R){
    if(L==R){adde(L,id1[o]=++tot,0);adde(id2[o]=++tot,L,0);}
    else{
        int lc=o<<1,rc=lc|1,M=L+R>>1;
        build(lc,L,M);build(rc,M+1,R);
        adde(id1[lc],id1[o]=++tot,0);adde(id1[rc],id1[o],0);
        adde(id2[o]=++tot,id2[lc],0);adde(id2[o],id2[rc],0);
    }
}
void ask(int o,int L,int R){
    if(x<=L&&y>=R){adde(id1[o],p,c);adde(p,id2[o],0);}
    else{
        int lc=o<<1,rc=lc|1,M=L+R>>1;
        if(x<=M)ask(lc,L,M);
        if(y>M)ask(rc,M+1,R);
    }
}
int main(){
    int n,m,i,u,v;
    node h;
    scanf("%d%d",&n,&m);
    build(1,1,tot=n);
    while(m--){
        scanf("%d%d%d",&x,&y,&c);p=++tot;
        ask(1,1,n);
    }
    memset(d,0x3f,sizeof(d));
    Q.push(node(1,d[1]=0ll));
    while(!Q.empty()){
        h=Q.top();Q.pop();
        if(d[u=h.p]!=h.d)continue;
        if(u==n){
            printf("%lld\n",d[n]);
            return 0;
        }
        for(i=G[u];i;i=nxt[i])if(d[u]+w[i]<d[v=to[i]])Q.push(node(v,d[v]=d[u]+w[i]));
    }
    puts("-1");
    return 0;
}
View Code

 

AGC 039

A:

除了边上相连的以外都是不变的,分类讨论即可。

#include<cstdio>
#include<cstring>
char s[105];
int len[105];
int main(){
    int n,k,i,cnt=1;
    long long ans=0ll;
    scanf("%s%d",s+1,&k);n=strlen(s+1);
    len[1]=1;
    for(i=2;i<=n;++i)if(s[i]!=s[i-1])len[++cnt]=1;
    else ++len[cnt];
    if(cnt==1){
        printf("%lld\n",1ll*n*k>>1ll);
        return 0;
    }
    for(i=2;i<cnt;++i)ans+=len[i]>>1;
    ans*=k;
    if(s[n]==s[1])ans+=1ll*(len[1]+len[cnt]>>1)*(k-1);
    else ans+=1ll*((len[1]>>1)+(len[cnt]>>1))*(k-1);
    printf("%lld\n",ans+(len[1]>>1)+(len[cnt]>>1));
    return 0;
}
View Code

B:

一定有一个点在一号集里,枚举这个点,就可以推出其余点。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
char s[205];
bool G[205][205];
int d[205],n;
queue<int> Q;
inline bool bfs(int u){
    int v;
    while(!Q.empty())Q.pop();
    d[u]=1;Q.push(u);
    while(!Q.empty()){
        u=Q.front();Q.pop();
        for(v=1;v<=n;++v)if(G[u][v])if(!d[v]){
            d[v]=d[u]+1;
            Q.push(v);
        }else if(d[v]!=d[u]+1&&d[v]!=d[u]-1)return 0;
    }
    return 1;
}
int main(){
    int i,j,ans=-1;
    scanf("%d",&n);
    for(i=1;i<=n;++i){
        scanf("%s",s+1);
        for(j=1;j<=n;++j)G[i][j]=s[j]=='1';
    }
    for(i=1;i<=n;++i){
        memset(d,0,sizeof(d));
        if(bfs(i))for(j=1;j<=n;++j)if(d[j]>ans)ans=d[j];
    }
    printf("%d\n",ans);
    return 0;
}
View Code

C:

首先所有串一定可以用2n次操作变回原样,因此只要寻找特殊串即可。

若记把$T$二进制取反后的串为$T'$,那么所有特殊串都可表示成为$TT'TT'\cdots TT'T$的形式,且操作次数为$2len_T$,枚举len,循环节比X前len位小的必然可行,大的必然不行,相等的构造出来暴力比,len顶多$O(\sqrt{n})$个(实际上远远达不到),可以AC。

注意len=9的种数可能会包含len=3的种数,所以还要减一下。

#include<cstdio>
typedef long long ll;
const int mod=998244353;
char s[200050];
bool a[200050],b[200050];
int n,ans=0,tmp[200050],res[200050];
inline bool cmp(){
    for(int i=1;i<=n;++i)if(a[i]!=b[i])return a[i]<b[i];
    return 1;
}
int main(){
    int i,j,k;
    scanf("%d%s",&n,s+1);
    for(i=1;i<=n;++i){
        b[i]=s[i]=='1';
        tmp[i]=((tmp[i-1]<<1)+b[i])%mod;
    }
    ans=(ll)(tmp[n]+1)*n*2%mod;
    for(k=1;k<=n/3;++k)if(!(n%k)&&n/k%2==1){
        res[k]=tmp[k];
        for(i=1;i<=k;++i)a[i]=b[i];
        for(;i<=n;i+=k)
            for(j=0;j<k;++j)a[i+j]=a[i+j-k]^1;
        if(cmp())res[k]=(res[k]+1)%mod;
        if(k>1)for(i=1;i*i<=k;++i)if(!(k%i)){
            res[k]=(res[k]-res[i]+mod)%mod;
            if(i*i!=k&&i!=1)res[k]=(res[k]-res[k/i]+mod)%mod;
        } 
        ans=(ans-(ll)res[k]*(n-k<<1)%mod+mod)%mod;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

AGC 038

A:

脑筋急转弯?

#include<cstdio>
bool A[1005][1005];
int main(){
    int n,m,a,b,i,j;
    scanf("%d%d%d%d",&n,&m,&b,&a);
    for(i=1;i<=a;++i)
        for(j=1;j<=b;++j)A[i][j]=1;
    for(i=a+1;i<=n;++i)
        for(j=b+1;j<=m;++j)A[i][j]=1;
    for(i=1;i<=n;++i){
        for(j=1;j<=m;++j)printf("%d",A[i][j]);
        putchar('\n');
    }
    return 0;
}
View Code

B:

两个相邻位置$i,i+1$执行操作后结果相同要求$a_i\le a_{i+1,i+2,\cdots,i+k}$且$a_{i+k}\ge a_{i,i+1,\cdots,i+k-1}$,可以单调队列维护,注意特判。

#include<cstdio>
int a[200050],b[200050];
struct que1{
    int q[200050],h,r;
    inline void init(){
        h=1;r=0;
    }
    inline void push(int x){
        while(h<=r&&x>q[r])--r;
        q[++r]=x;
    }
    inline void pop(int x){if(x==q[h])++h;}
}Q;
struct que2{
    int q[200050],h,r;
    inline void init(){
        h=1;r=0;
    }
    inline void push(int x){
        while(h<=r&&x<q[r])--r;
        q[++r]=x;
    }
    inline void pop(int x){if(x==q[h])++h;}
}q;
int main(){
    int n,k,i,cnt=1,ans=1;
    bool f;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;++i)scanf("%d",a+i);
    for(b[1]=1,i=2;i<=n;++i)if(a[i]>a[i-1])b[i]=b[i-1];
    else b[i]=++cnt;
    Q.init();q.init();
    for(i=1;i<=k;++i)Q.push(a[i]),q.push(a[i]);
    f=b[k]==b[1];
    for(;i<=n;++i){
        Q.pop(a[i-k]);q.pop(a[i-k]);
        if(q.q[q.h]<a[i-k]||a[i]<Q.q[Q.h])if(b[i]==b[i-k+1])if(!f){++ans;f=1;}
        else;
        else ++ans;
        Q.push(a[i]);q.push(a[i]);
    }
    printf("%d\n",ans);
    return 0;
}
View Code

C:

首先$lcm(a,b)=\frac{ab}{gcd(a,b)}$,再构造数列$w$满足$\sum\limits_{d|n}w_d=\frac{1}{n}$(这个可以用一个个减的方法得到),那么$ans=\sum\limits_d\sum\limits_{d|a_i}\sum\limits_{i<j,d|a_j}w_da_ia_j$,可以枚举$d$后算出。

#include<cstdio>
typedef long long ll;
const int mod=998244353;
int w[1000050],cnt[1000050];
int main(){
    int n,m=0,i,j,x,sum,ans=0;
    scanf("%d",&n);
    for(i=0;i<n;++i){
        scanf("%d",&x);
        if(x>m)m=x;
        ++cnt[x];
    }
    for(i=2,w[1]=1;i<=m;++i)w[i]=(ll)(mod-mod/i)*w[mod%i]%mod;
    for(i=1;i<=(m>>1);++i)
        for(j=(i<<1);j<=m;j+=i){w[j]-=w[i];if(w[j]<0)w[j]+=mod;}
    for(i=1;i<=m;++i){
        for(j=i,sum=0;j<=m;j+=i){
            ans=(ans+((ll)sum*j%mod*cnt[j]+((ll)cnt[j]*(cnt[j]-1)>>1ll)%mod*j%mod*j)%mod*w[i])%mod;
            sum=(sum+(ll)j*cnt[j])%mod;
        }
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

Japanese Student  Championship 2019 Qualification

A:

送分题,$O(md)$暴力即可。

#include<cstdio>
int main(){
    int m,d,i,j,ans=0;
    scanf("%d%d",&m,&d);
    for(i=1;i<=m;++i)
        for(j=22;j<=d;++j)if(j/10>=2&&j%10>=2&&(j/10)*(j%10)==i)++ans;  //22以前的日期十位必然<2
    printf("%d\n",ans);
    return 0;
}
View Code

B:

把一个序列复制k份,首先序列内逆序对数会乘k,而对于跨序列的情况,对于第$i$个序列里的一个数$a$,它额外的逆序对数是$\text{序列内比a大的数的个数}\times (i-1)$,所以所有$a$的总贡献就是$\text{序列内比a大的数的个数}\times\frac{k(k-1)}{2}$。因为$n\le 2000$很小,直接$O(n^2)$暴力求就好了。

注意第三个样例是10 9 8 7 5 6 3 4 2 1

#include<cstdio>
typedef long long ll;
const int mod=1000000007;
int a[2005];
int main(){
    int n,k,i,j,res,ans=0;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;++i)scanf("%d",a+i);
    for(i=2;i<=n;++i)
        for(j=1;j<i;++j)if(a[j]>a[i])++ans;
    ans=(ll)ans*k%mod;
    for(i=1;i<=n;++i){
        for(j=1,res=0;j<=n;++j)if(a[j]>a[i])++res;
        ans=(ans+(ll)res*k%mod*(k-1)%mod*500000004)%mod;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

C:

应该发现的一个事实是$(l_1,r_1),(l_2,r_2)$和$(l_1,r_2),(l_2,r_1)$产生的效果是相同的。

另一个结论比较难发现:每个位置要么作为l,要么作为r,不存在某个位置既能作l又能作r

因为最左边显然为l,而对于WW或BB的情况,前后两个不能均为l或均为r;同时,对于BW或WB的情况,前后两个必须均为l或r(否则将无法把它们都变成W)。

若最左边或最右边为W(它们不能被改回来),或l,r位置数目不等则无解,否则把l,r适当配对即可,扫描线一下就可以得出方案数,复杂度$O(n)$。

#include<cstdio>
typedef long long ll;
const int mod=1000000007;
char s[200050];
bool d[200050];
int sum[200050];
int main(){
    int n,i,ans=1,cnt=0;
    scanf("%d%s",&n,s+1);
    if(s[1]=='W'||s[n<<1]=='W'){
        puts("0");
        return 0;
    }
    for(i=2,d[1]=0,sum[1]=1;i<=(n<<1);++i)sum[i]=sum[i-1]+!(d[i]=d[i-1]^(s[i]==s[i-1]));
    if(sum[n<<1]!=n){
        puts("0");
        return 0;
    }
    for(i=2;i<=(n<<1);++i)if(d[i]){
        ans=(ll)ans*(sum[i-1]-cnt)%mod;
        ++cnt;
    }
    for(i=2;i<=n;++i)ans=(ll)ans*i%mod;
    printf("%d\n",ans);
    return 0;
}
View Code

D:

转化题意:已知一个n个结点的完全图,请用尽量少的颜色将边染色,使图上不存在同色的奇环。

一个很好想的思路是按照$|u-v|$的奇偶性连边,但这样连是错误的:(1,3),(3,5),(1,5)均为偶边。所以想到(1,5)要用第三种颜色,由此想到根据$|u-v|$的二进制最低位连边。

为什么这样是正确的呢?考虑一个点$u$,如果从它出发有同色奇环,则从它出发,沿偶数条同色边可以走到一个与它直接用这一色边相连的结点,而我们知道$u+2^i\times 2k=u+2^{i+1}\times k$,即从$u$出发后走偶数条$i$色边后到达的点和它连边的颜色至少为$i+1$,故奇环不存在。

复杂度$O(n^2logn)$。

#include<cstdio>
inline int getit(int x){
    int t=x&-x,res=0;
    while(t){t>>=1;++res;}
    return res;
}
int main(){
    int n,i,j;
    scanf("%d",&n);
    for(i=1;i<n;++i){
        for(j=i+1;j<=n;++j)printf("%d ",getit(j-i));
        putchar('\n');
    }
    return 0;
}
View Code

 

AGC 037

A:

没想到dpQAQ。考虑贪心,将$s$分解为若干个只含相同字符的串的链接,记每个串内有$cnt_i$个字符。发现$cnt_i\;mod\;3=2$时,拼上一个才有利;$cnt_i\;mod\;3=2$时,拆一个往后拼必赚;$cnt_i\;mod\;3=1$时,拆一个往后拼必亏;$cnt_i\;mod\;3=0$时,拆一个往后拼不赚不亏。但是考虑下面的例子:

aabbbaa

最优解是将中间的bbb拆两个分给两边,所以$cnt_i\;mod\;3=0$时也要拆掉。

复杂度$O(n)$。

#include<cstdio>
#include<cstring>
char s[200050],c[200050];
int cnt[200050];
int main(){
    int n,m=1,i,ans=0;
    scanf("%s",s);n=strlen(s);
    c[1]=s[0];cnt[1]=1;
    for(i=1;i<n;++i)if(s[i]!=c[m]){c[++m]=s[i];cnt[m]=1;}
    else ++cnt[m];
    for(i=m-1;i;--i)if((cnt[i]%3==0||cnt[i]%3==2)&&cnt[i+1]%3==2){
        --cnt[i];--cnt[i+1];
        ++ans;
    }
    for(i=1;i<=m;++i)ans+=cnt[i]/3*2+(cnt[i]%3!=0);
    printf("%d\n",ans);
    return 0;
}
View Code

B:

推错式子导致白费工夫+没做出,于是掉rating了。考虑记第$i$个$R,G,B$出现的位置为$r_i,g_i,b_i$,记$A_i=\min(r_i,g_i,b_i),C_i=\max(r_i,g_i,b_i),B_i=\text{剩下的那个}$,则最小贡献为$\sum\limits^n_{i=1}(C_i-A_i)$,方案数就是把它们配对满足$A_j<B_j<C_j$的方案数。最后乘上$n!$。

复杂度$O(n)$。

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int mod=998244353;
char s[300050];
int A[100050],B[100050],C[100050];
vector<int> a,b,c;
int main(){
    int n,i,x,ans=1;
    scanf("%d%s",&n,s+1);
    for(i=1;i<=n*3;++i)if(s[i]=='R')a.push_back(i);
    else if(s[i]=='G')b.push_back(i);
    else c.push_back(i);
    for(i=0;i<n;++i)if(a[i]<b[i])if(a[i]<c[i]){
        A[i+1]=a[i];
        if(b[i]<c[i]){B[i+1]=b[i];C[i+1]=c[i];}
        else{B[i+1]=c[i];C[i+1]=b[i];}
    }else{A[i+1]=c[i];B[i+1]=a[i];C[i+1]=b[i];}
    else if(b[i]<c[i]){
        A[i+1]=b[i];
        if(a[i]<c[i]){B[i+1]=a[i];C[i+1]=c[i];}
        else{B[i+1]=c[i];C[i+1]=a[i];}
    }else{A[i+1]=c[i];B[i+1]=b[i];C[i+1]=a[i];}
    for(i=1;i<=n;++i){
        x=upper_bound(A+1,A+n+1,B[i])-A-1;
        ans=(ll)ans*(x-i+1)%mod*i%mod;
    }
    for(i=n;i;--i){
        x=lower_bound(C+1,C+n+1,B[i])-C;
        ans=(ll)ans*(i-x+1)%mod;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

C:

对于终止状态,考虑最后得到的那个数,它肯定是加上两边的数得到的,而两边的数都是确定的!所以倒退,看是否能回到原始状态即可。

实现时,找出所有满足$b_i>a_i$且$b_i-a_i\ge b_{i-1}+b_{i+1}$的结点,很明显这些点不会相邻,所以答案与选择顺序无关,同时每次修改只会影响两侧的点,队列/栈模拟,复杂度$O(nloga_i)$。

#include<cstdio>
#include<queue>
using namespace std;
int f[200050],a[200050],n;
bool inq[200050];
inline int lst(int x){return x-1==0?n:x-1;}
inline int nxt(int x){return x+1>n?1:x+1;}
struct node{
    int p;
    node(){}
    node(int p):p(p){}
};
queue<node> Q;
inline bool check(int i){return a[i]>f[i]&&a[i]-f[i]>=a[lst(i)]+a[nxt(i)];}
int main(){
    int i,t1,t2;
    long long ans=0ll;
    scanf("%d",&n);
    for(i=1;i<=n;++i)scanf("%d",f+i);
    for(i=1;i<=n;++i){
        scanf("%d",a+i);
        if(a[i]<f[i]){
            puts("-1");
            return 0;
        }
    }
    for(i=1;i<=n;++i)if(check(i))Q.push(node(i)),inq[i]=1;
    while(!Q.empty()){
        i=Q.front().p;Q.pop();inq[i]=0;
        t1=a[i]-f[i];
        t2=a[lst(i)]+a[nxt(i)];
        ans+=t1/t2;
        a[i]=f[i]+t1%t2;
        if(!inq[lst(i)]&&check(lst(i)))Q.push(lst(i)),inq[lst(i)]=1;
        if(!inq[nxt(i)]&&check(nxt(i)))Q.push(nxt(i)),inq[nxt(i)]=1;
    }
    for(i=1;i<=n;++i)if(f[i]!=a[i]){
        puts("-1");
        return 0;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

D:

要让第3步之后排完,第3步之前肯定各行的数集是$(1,2,\cdots,m),(m+1,m+2,\cdots,2m),\cdots,((n-1)m+1,(n-1)m+2,\cdots,nm)$。所以第二步开始时各列的$n$个数应恰好分别属于$n$个集,以列和集为左/右点建二分图,问题转化为把$nm$条边组织成$m$个完美匹配,Dinic复杂度$O(nm^2\sqrt{n})$。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int a[105][105],b[105][105],G[205],to[20405],cap[20405],nxt[20405],sz=-1,d[205],cur[205],id[105][105],n,tmp[105];
bool used[105][105];
queue<int> Q;
inline void adde(int u,int v,int c){
    to[++sz]=v;cap[sz]=c;nxt[sz]=G[u];G[u]=sz;
    to[++sz]=u;cap[sz]=0;nxt[sz]=G[v];G[v]=sz;
}
inline bool bfs(){
    int i,u,v;
    memset(d,0x3f,sizeof(d));
    d[0]=0;Q.push(0);
    while(!Q.empty()){
        u=Q.front();Q.pop();
        for(i=G[u];i!=-1;i=nxt[i])if(cap[i]&&d[v=to[i]]==0x3f3f3f3f){
            d[v]=d[u]+1;
            Q.push(v);
        }
    }
    return d[n<<1|1]!=0x3f3f3f3f;
}
int dfs(int u,int a){
    if(u==(n<<1|1)||!a)return a;
    int v,flow=0,f;
    for(int &i=cur[u];i!=-1;i=nxt[i])if(d[v=to[i]]==d[u]+1&&(f=dfs(v,min(a,cap[i])))){
        flow+=f;
        cap[i]-=f;cap[i^1]+=f;
        if(!(a-=f))break;
    }
    return flow;
}
inline void dinic(){
    while(bfs()){
        memcpy(cur,G,sizeof(cur));
        dfs(0,0x3f3f3f3f);
    }
}
int main(){
    int m,i,j,k;
    scanf("%d%d",&n,&m);
    memset(G,-1,sizeof(G));
    for(i=1;i<=n;++i){adde(0,i,0);adde(i+n,n<<1|1,0);}
    for(i=1;i<=n;++i)
        for(j=1;j<=m;++j){
            scanf("%d",&a[i][j]);
            id[i][j]=sz+1;
            adde(i,(a[i][j]+m-1)/m+n,1);
        }
    for(i=1;i<=m;++i){
        for(j=0;j<(n<<2);j+=4){++cap[j];++cap[j+2];}
        dinic();
        for(j=1;j<=n;++j)
            for(k=1;k<=m;++k)if(!used[j][k]&&!cap[id[j][k]]){
                b[j][i]=a[j][k];
                used[j][k]=1;
                cap[id[j][k]^1]=0;
            }
    }
    for(i=1;i<=n;++i){
        for(j=1;j<=m;++j)printf("%d ",b[i][j]);
        putchar('\n');
    }
    for(j=1;j<=m;++j){
        for(i=1;i<=n;++i)tmp[i]=b[i][j];
        sort(tmp+1,tmp+n+1);
        for(i=1;i<=n;++i)b[i][j]=tmp[i];
    }
    for(i=1;i<=n;++i){
        for(j=1;j<=m;++j)printf("%d ",b[i][j]);
        putchar('\n');
    }
    return 0;
}
View Code

 

posted @ 2019-08-19 15:17  wangyuchen  阅读(227)  评论(0编辑  收藏  举报