FOJ-2011年11月月赛

来源:互联网 发布:oppo软件删不掉怎么办 编辑:程序博客网 时间:2024/06/05 18:01

学长给开题做的,随机队员时运气不好,把自己队的随走了一个,就剩zcy和我两个人打的。开局还行,但是毕竟人少,没法很快连续出题,后来出题速度就慢了。
A:
FZU 2054
水题,判断最大值在哪边,输出。

#include<cstdio>#include<algorithm>using namespace std;const int inf=0x3f3f3f3f;const int maxn=10010;int main(){    int t;    scanf("%d",&t);    while(t--){        int t1,t2;        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        t1=max(a,b),t1=max(t1,c);        scanf("%d%d%d",&a,&b,&c);        t2=max(a,b),t2=max(t2,c);        printf("%d\n",t1>t2?1:2);    }    return 0;}

B:
FZU 2055
一开始我敲,敲了一半发现错了,后来zcy敲的。发现自己之前想麻烦了,数据量少,直接暴力就行。

#include<iostream>#include<string>using namespace std;string s[108],p,t;int n,op;bool path(string p,string d){    int len=p.length();    if(len>=d.length()) return false;    for(int i=0;i<len;++i){        if(p[i]!=d[i]) return false;    }    return true;}bool duc(string t,string d){    int lt=t.length(),ld=d.length();    if(lt>ld) return false;    for(int i=lt-1,j=ld-1;i>=0;--i,--j){        if(t[i]!=d[j]) return false;    }    return true;}void judge(string p,string t){    for(int i=0;i<n;++i)        if(path(p,s[i])&&duc(t,s[i]))            cout << s[i] <<endl;    return ;}int main(){    ios::sync_with_stdio(false);    int T;    cin >> T;    while(T--){        cin >> n >> op;        for(int i=0;i<n;++i)            cin >> s[i];        for(int i=0;i<op;++i){            cin >> p >> t;            judge(p,t);        }    }    return 0;}

C:
FZU 2056
比赛时没想到,赛后问了学长思路,DP所有矩形的面积,二分搜索最大边长。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1010;int n,m,lim;int d[maxn][maxn];bool ok(int h){    for(int i=h;i<=n;++i)        for(int j=h;j<=m;++j)            if(d[i][j]-d[i-h][j]-d[i][j-h]+d[i-h][j-h]<=lim) return true;    return false;}int main(){    int t;scanf("%d",&t);    while(t--){        memset(d,0,sizeof(d));        scanf("%d%d%d",&n,&m,&lim);        for(int i=1;i<=n;++i)            for(int j=1;j<=m;++j){                int k;                scanf("%d",&k);                d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+k;            }        int top=min(n,m),bott=0,best=0;        while(bott<=top){            int mid=(top-bott)/2+bott;            if(ok(mid)) best=max(best,mid*mid),bott=mid+1;            else top=mid-1;        }        printf("%d\n",best);    }    return 0;}

D:
比赛时看成是1w*1w的数据量,要写类似并查集的树。赛后补题时发现是1w * 100。
记录每个人的性别和孩子编号。然后查询就好。

#include<cstdio>#include<cstring>using namespace std;const int maxn=10010;int ch[maxn],len;bool sex[maxn];char ans[maxn];bool f(int k,int x,int y){    len=0;    while(ch[y]){        ans[len++]=sex[y]?'M':'F';        if(x==(y=ch[y])){            printf("%d ",k);            for(int i=len-1;i>=0;--i) putchar(ans[i]);            puts("");            return true;        }    }    return false;}int main(){    int t;scanf("%d",&t);    while(t--){        memset(ch,0,sizeof(ch));        memset(sex,0,sizeof(sex));        int n;scanf("%d",&n);        int num=n/2;        for(int i=0;i<num;++i){            int cur,f,m;            scanf("%d%d%d",&cur,&f,&m);            ch[f]=ch[m]=cur,sex[m]=true;        }        int q;scanf("%d",&q);        while(q--){            int x,y;            scanf("%d%d",&x,&y);            if(!f(1,x,y)&&!f(0,y,x)) printf("Relative\n");        }    }    return 0;}

E:
FZU 2058
比赛时用STL写的O(nlogn)算法超时,最后没改数组写。
赛后得知可以用O(n)算法,所以赛后补了这道。两个指针从前后分别遍历数组,满足条件时统计个数。

#include<cstdio>#include<algorithm>using namespace std;typedef long long LL;const int maxn=100010;int a[maxn];int Scan(){    int res=0,ch,flag=0;    if((ch=getchar())=='-') flag=1;    else if(ch>='0'&&ch<='9') res=ch-'0';    while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';    return flag?-res:res;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m)){        getchar();        for(int i=0;i<n;++i) a[i]=Scan();        sort(a,a+n);        LL ans=0;        int l=0,r=n-1;        while(l<=r){            if(a[l]==a[r]){                if(a[l]+a[r]==m) ans+=LL(r-l)*(r-l+1)/2;                break;            }            if(a[l]+a[r]==m){                int ll=l,rr=r;                while(a[l]==a[ll]) ++l;                while(a[r]==a[rr]) --r;                ans+=LL(l-ll)*(rr-r);            }            else if(a[l]+a[r]>m) --r;            else ++l;        }        printf("%I64d\n",ans);    }    return 0;}

H:
FZU 2061
比赛时准备找规律过掉这道题,快结束了得知找钱可以找好几张,之前推的不对。看也来不及推了,就和zj交流经验,再后来zcy按照zj说的过掉了这道题。。
打3^0~3^n和的表。对每个输入遍历计数,输出。

#include<stdio.h>#include<math.h>int main(){    int num[36];    num[0]=1;    for(int i=1;i<20;++i)        num[i]=num[i-1]+pow(3,i);    int n;    while(~scanf("%d",&n)){        int ans=1;        for(int i=0;i<20;++i){            if(n>num[i]) ++ans;            else break;        }        printf("%d\n",ans);    }    return 0;}

I:
FZU 2062
开场我翻题时看到题目配图说是水题,就跟zcy说了,我提出思路,他感觉正确,就打了交过了。
一开始思路不太对,导致最后代码很挫。

#include<cstdio>using namespace std;const int inf=0x3f3f3f3f;const int maxn=10010;int d(int k){    if(k==1) return 1;    return d(k>>1)+1;}int main(){    int n;    while(~scanf("%d",&n))        printf("%d\n",d(n));    return 0;}

J:
FZU 1859
zcy读到说是个画图的水题,我写出来,一块Debug之后过的。
对每个图分四份递归,然后输出就好。

#include<cstdio>#include<cstring>using namespace std;const int inf=0x3f3f3f3f;const int maxn=1030;char g[maxn][maxn];void draw(int n,int l1,int l2,int r1,int r2){    if(n==1){g[l1][r1]='@';return;}    int k=1<<(n-2);    draw(n-1,l1,l1+k,r1,r1+k);    draw(n-1,l2-k,l2,r1,r1+k);    draw(n-1,l2-k,l2,r2-k,r2);    return;}int main(){    int n;    while(~scanf("%d",&n)&&n){        memset(g,' ',sizeof(g));        draw(n,0,1<<(n-1),0,1<<(n-1));        int k=1<<(n-1);        for(int i=0;i<k;++i){            for(int j=k-1;j>=0;--j)                if(g[i][j]=='@') {g[i][j+1]=0;break;}            puts(g[i]);        }        puts("");    }    return 0;}

K:
比赛时以为是用线段树做,所以敲了线段树,用书上模板坑了好久。赛后学长说可以DP求,补了一个用DP过的。
n=1000,m=100000。
线段树的建树复杂度O(nlogn),查询复杂度O(mlogn),总复杂度O(mlogn)。
DP处理数据复杂度O(n^2),查询复杂度O(1),总复杂度O(n^2)。
还是DP更快一些。
更重要的是,个人感觉DP好写,写线段树容易出错。

//DP版:#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1010;int d[maxn][maxn];int main(){    int tt=0,n;    while(~scanf("%d",&n)){        memset(d,0,sizeof(d));        for(int i=1;i<=n;++i) scanf("%d",&d[i][i]);        for(int i=1;i<=n;++i){            for(int j=i+1;j<=n;++j)                d[i][j]=max(d[i][j-1],d[j][j]);        }        int q;scanf("%d",&q);        printf("Case #%d:\n",++tt);        while(q--){            int l,r;scanf("%d%d",&l,&r);            printf("%d\n",l<=r?d[l][r]:max(d[1][r],d[l][n]));        }        puts("");    }    return 0;}
//线段树版:#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf=0x3f3f3f3f;const int maxn=1010;int cnt,n,d[(1<<12)-1];void init(int n_){    cnt=0,n=1;    while(n<n_) n<<=1,++cnt;    memset(d,-1,sizeof(d));}int q(int a,int b,int k,int l,int r){    if(r<=a||b<=l) return -1;    if(a<=l&&r<=b) return d[k+1];    return max(q(a,b,2*k+1,l,(l+r)/2),q(a,b,2*k+2,(l+r)/2,r));}int main(){    int tt=0;    while(~scanf("%d",&n)){        int tmp=n;        init(n);        for(int i=1<<cnt;i<(1<<cnt)+tmp;++i) scanf("%d",&d[i]);        int t=cnt-1;        while(t>=0){            int num=1<<(cnt-t);            for(int i=1<<t;i<1<<(t+1);++i)                d[i]=max(d[i*2],d[i*2+1]);            --t;        }        int m;        scanf("%d",&m);        printf("Case #%d:\n",++tt);        for(int i=0;i<m;++i){            int l,r;            scanf("%d%d",&l,&r);            --l,--r;            int ans=-1;            if(l>r) ans=max(q(0,r+1,0,0,n),q(l,n,0,0,n));            else ans=q(l,r+1,0,0,n);            printf("%d\n",ans);        }        printf("\n");    }    return 0;}

写在后面:
开场我从前往后读,zcy从后往前读。
前面的中文,读得快,我看A水,直接打了交,A1y(3)。然后继续看B是模拟,不想写模拟,跳过。C不会,D以为要建树,跳过。
E~K是英文题,挨个点着看了一遍。看到I,图上说这是水题,我就读了一遍,跟zcy讲了题意。我们感觉可做,但因为是数学,准备先放一放,一会再做。继续读题。
读别的题时,灵光乍现,感觉是二分一类的做法,跟zcy说了一下,他感觉对。就敲了,一开始想成分奇偶讨论了,所以写成递归,后来发现只需要数位数就行。提交I1y(13)。
再后来,我敲B,zcy读题,读到J水,跟我说了。原本准备敲完B之后再弄,但是后来发现B敲错了。就开始做J,一块Debug之后过了,提交,交在E题上了,重交J1y(55)。至此打得还不错,三道都是1y,都是FB。
再往后就有点乱了,开始看E,用map写的,不过脑补复杂度O(nlogn),应该是STL差个常数。跳过,看其他题。
zcy给我讲K题意,我以为是线段树,我开始敲K。敲了好久样例不过。下机器,zcy敲B。Debug过程中,zcy在我的多次干扰下过掉了B,B1y(150)。
之后我继续上机改K,两次WA之后,K3y(168)。
再往后我们几乎没正经打了,尝试了使用hash_map/hash_set过E,CE,找CB头文件粘上,依然CE。后来的时间大部分都在猜H题解法,直到最后与其他队成员交流经验,莫名其妙的过掉了,中途CE两次,H3y(295)。
赛后问了学长其他几道题的做法,补了几道题。

0 0