Codeforces Round #234 (Div. 2)

来源:互联网 发布:飞天特效软件下载 编辑:程序博客网 时间:2024/05/29 04:41

           CF回滚以后掉到蓝名了,打了一场勉强回到div1,D最后复测竟然挂了,好伤心。。。

A Inna and Choose Options

         长度为12的OX的序列,要排成a×b的矩阵,使得矩阵有一列全为X。很简单。随便枚举一下就行了。。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;char str[20];char tmp[20][20];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t;    scanf("%d",&t);    vector<pair<int,int> >ans;    while(t--)    {        scanf("%s",str);        ans.clear();        for(int b=12;b>=1;--b)        {            if(12%b!=0) continue;            int a=12/b;            bool flag=false;            for(int j=0;j<b;++j)            {                bool canit=true;                for(int i=0;i<a;++i)                    if(str[i*b+j]!='X') {canit=false;break;}                if(canit) {flag=true;break;}            }            if(flag) ans.push_back(make_pair(a,b));        }        int size=ans.size();        printf("%d",size);        for(int i=0;i<size;++i)        {            printf(" %dx%d",ans[i].first,ans[i].second);        }        printf("\n");    }    return 0;}



B - Inna and New Matrix of Candies

         这题最开始看了半天楞是没看懂,只要先去做C。。。其实就是给出一个矩阵,每一行只有一个G和一个S其他都是*,现在要把每一行的G都移动到S处。每次可以选若干行,使这一行的G同时向右移动,直到有一个G到达S或到达矩阵最右段。问最少需要多少操作。。先算一下每个G到达S的步数,接下来让离得最近的到达S,同时所有的G移动,然后让离得第二近的移动……只要排个序搞一下就行了。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=1000+10;char str[maxn][maxn];int step[maxn];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n,m;    scanf("%d%d",&n,&m);    for(int i=0;i<n;++i)        scanf("%s",str[i]);    bool cansolve=true;    for(int i=0;i<n;++i)    {        bool flag=false;        int last=-1;        for(int j=0;j<m;++j)        {            if(str[i][j]=='G')                {last=j;flag=true;}            else if(str[i][j]=='S')            {                if(last==-1) break;                step[i]=j-last;            }        }        if(!flag) {cansolve=false;break;}    }    if(!cansolve)        printf("-1\n");    else    {        int cnt=0;        sort(step,step+n);        int k=n;        while(true)        {            cnt++;            int val=step[0];            int i=1;            for(i=1;i<k;++i)                step[i]-=val;            step[0]=0;            i=0;            while(step[i]==0&&i<k) i++;            if(i==k) break;            for(int j=0;j<k-i;++j)                step[j]=step[i+j];            k=k-i;        }        printf("%d\n",cnt);    }    return 0;}

C - Inna and Huge Candy Matrix

      给出一个n×m的矩阵,有p个位置有糖果,现在将这个矩阵顺时针旋转x次,翻转矩阵的行y次,逆时针旋转z次,问最后这p个点的位置。在纸上画一画就会发现每个操作后的位置都可以算出来,这样,将x,y,分别对4,2,4取模,然后依次模拟相应操作计算坐标就行了。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;struct Point{    int x,y;    Point(){}    Point(int x,int y):x(x),y(y) {}}pt[maxn];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n,m,X,Y,Z,p;    scanf("%d%d%d%d%d%d",&n,&m,&X,&Y,&Z,&p);    for(int i=0;i<p;++i)        scanf("%d%d",&pt[i].x,&pt[i].y);    X=X%4;Y%=2;Z%=4;    int N=n,M=m;    for(int i=0;i<p;++i)    {        n=N,m=M;        int x=pt[i].x,y=pt[i].y;        if(X==1) pt[i]=Point(y,n-x+1),swap(n,m);        else if(X==2) pt[i]=Point(n-x+1,m-y+1);        else if(X==3) pt[i]=Point(m-y+1,x),swap(n,m);        x=pt[i].x,y=pt[i].y;        if(Y) pt[i]=Point(x,m-y+1);        x=pt[i].x,y=pt[i].y;        if(Z==3) pt[i]=Point(y,n-x+1);        else if(Z==2) pt[i]=Point(n-x+1,m-y+1);        else if(Z==1) pt[i]=Point(m-y+1,x);        printf("%d %d\n",pt[i].x,pt[i].y);    }    return 0;}


D - Dima and Bacteria

       感觉这题也好难理解。。。有n个细菌,将这些细菌分为k种,每种有c[i]个,接下来有m条边表示从某个细菌到另一个细菌所需要耗费的能量。如果同种细菌之间任意两个细菌相互到达所需要的能量为0,那么就输出yes并输出不同种类细菌之间的最短距离。需要注意两个同种细菌可以经过其他不同种类的细菌到达。理解题意以后就比较简单了,如果边权为0,那么用并查集把这两个点合并,最后看相同种类的细菌是否都在同一个集合中。最后floyd一下就行了。


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;struct Edge{    int v,w,next;    Edge(){}    Edge(int v,int w,int next):v(v),w(w),next(next){}}edges[maxn<<1];int head[maxn],nEdge;int type[maxn],c[maxn];int pa[maxn];int d[550][550];void AddEdges(int u,int v,int w){    edges[++nEdge]=Edge(v,w,head[u]);    head[u]=nEdge;    edges[++nEdge]=Edge(u,w,head[v]);    head[v]=nEdge;}int Find(int x){    return x==pa[x]?x:pa[x]=Find(pa[x]);}void Uion(int x,int y){    int a=Find(x),b=Find(y);    if(a!=b) pa[b]=a;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n,m,k;    scanf("%d%d%d",&n,&m,&k);    int cnt=0,u,v,w;    memset(head,0xff,sizeof(head));    memset(d,0x3f,sizeof(d));    nEdge=-1;    for(int i=1;i<=n;++i) pa[i]=i;    for(int i=1;i<=k;++i)    {        scanf("%d",&c[i]);        for(int j=0;j<c[i];++j)            type[++cnt]=i;    }    for(int i=0;i<m;++i)    {        scanf("%d%d%d",&u,&v,&w);        AddEdges(u,v,w);        if(w==0)            Uion(u,v);        if(type[u]!=type[v])            d[type[u]][type[v]]=d[type[v]][type[u]]=min(d[type[u]][type[v]],w);    }    cnt=1;    bool flag=true;    for(int i=1;i<=k&&flag;++i)    {        int fa=Find(cnt);        for(int j=0;j<c[i];++j)            if(Find(cnt+j)!=fa) {flag=false;break;}        cnt+=c[i];    }    if(!flag)        printf("No\n");    else    {        for(int i=1;i<=k;++i) d[i][i]=0;        for(int v=1;v<=k;++v)            for(int i=1;i<=k;++i)                for(int j=1;j<=k;++j)                    d[i][j]=min(d[i][j],d[i][v]+d[v][j]);        printf("Yes\n");        for(int i=1;i<=k;++i)        {            for(int j=1;j<=k;++j)            {                if(j!=1) printf(" ");                if(d[i][j]==inf) d[i][j]=-1;                printf("%d",d[i][j]);            }            printf("\n");        }    }    return 0;}

E - Inna and Binary Logic

       最初给出n个序列,对序列要进行n-1次操作,每次令ai[k] = ai - 1[kAND ai - 1[k + 1].问所有操作过程中的序列的和。开始没什么思路,看了看过掉的代码,发现完全看不懂这些大牛们的高大上的方法,不过也有所启发,yy了一下,想了个麻烦的方法、、、、首先把每个数按位建17棵线段树,对于每一位,将整个操作列出来可以发现,如果这个序列每有连续k个1,那么最终操作的总和就要加上(k+1)*k/2。想了想,利用线段树区间合并的方法貌似能搞,val[]表示操作完这个区间后的总和,sum[]表示区间里1的个数,pre[]表示区间最长连续1的前缀数,suff[]表示区间最长连续的1的后缀数。然后用线段树维护即可。。。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;int num[maxn];struct SegTree{    int sum[maxn<<2],pre[maxn<<2],suff[maxn<<2];    ll val[maxn<<2];    int bitp;    void PushUp(int l,int r,int rt)    {        int m=(l+r)>>1;        sum[rt]=sum[rt<<1]+sum[rt<<1|1];        if(sum[rt<<1]==m-l+1)            pre[rt]=sum[rt<<1]+pre[rt<<1|1];        else pre[rt]=pre[rt<<1];        if(sum[rt<<1|1]==r-m)            suff[rt]=suff[rt<<1]+sum[rt<<1|1];        else            suff[rt]=suff[rt<<1|1];        if(suff[rt<<1]&&pre[rt<<1|1])        {            val[rt]=val[rt<<1]+val[rt<<1|1];            ll tmp=suff[rt<<1];            val[rt]-=tmp*(tmp+1)/2;            tmp=pre[rt<<1|1];            val[rt]-=tmp*(tmp+1)/2;            tmp=suff[rt<<1]+pre[rt<<1|1];            val[rt]+=tmp*(tmp+1)/2;        }        else            val[rt]=val[rt<<1]+val[rt<<1|1];    }    void build(int l,int r,int rt)    {        if(l==r)        {            val[rt]=sum[rt]=pre[rt]=suff[rt]=(num[l]>>bitp)&1;            return ;        }        int m=(l+r)>>1;        build(l,m,rt<<1);        build(m+1,r,rt<<1|1);        PushUp(l,r,rt);    }    void Update(int p,int l,int r,int rt,int v)    {        if(l==r)        {            sum[rt]=val[rt]=pre[rt]=suff[rt]=v;            return ;        }        int m=(l+r)>>1;        if(m>=p) Update(p,l,m,rt<<1,v);        else Update(p,m+1,r,rt<<1|1,v);        PushUp(l,r,rt);    }}tree[17];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i)        scanf("%d",&num[i]);    for(int i=0;i<17;++i)    {        tree[i].bitp=i;        tree[i].build(1,n,1);    }    int p,v;    ll sum;    while(m--)    {        scanf("%d%d",&p,&v);        sum=0;        for(int i=0;i<17;++i)        {            tree[i].Update(p,1,n,1,(v>>i)&1);            sum+=(1<<i)*tree[i].val[1];        }        printf("%I64d\n",sum);    }    return 0;}


0 0
原创粉丝点击