您的位置:首页 > 其它

codeforces #549 Looksery Cup 部分题解

2015-06-09 17:28 337 查看
掉Rating快乐~~

A.Face Detection

题目大意:给定一个n∗mn*m的矩阵,求有多少2∗22*2的子矩形满足单词“face”的每个字母在矩形中恰好出现一次

签到题

[code]#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 55
using namespace std;
int n,m,ans;
char map[M][M];
int main()
{
    int i,j;
    cin>>n>>m;
    for(i=1;i<=n;i++)
        scanf("%s",map[i]+1);
    for(i=1;i<n;i++)
        for(j=1;j<m;j++)
        {
            char s[4]={map[i][j],map[i+1][j],map[i][j+1],map[i+1][j+1]};
            sort(s,s+4);
            if(s[0]=='a'&&s[1]=='c'&&s[2]=='e'&&s[3]=='f')
                ++ans;
        }
    return cout<<ans<<endl,0;
}


B.Looksery Party

题目大意:给定一个n∗nn*n的01矩阵AA,满足Ai,i=1A_{i,i}=1,以及一个1∗n1*n的行向量BB

输出一个{1,2,...,n}\{1,2,...,n\}的子集SS,令C=∑i∈SAiC=\sum_{i\in S}A_i,要求Ci≠BiC_i\neq B_i

令集合TT为当前满足Ci=BiC_i=B_i的所有ii的集合,然后进行如下操作:

while(TT非空)

{

任选x∈Tx\in T,将xx从TT集合删除,加入集合SS

C←C+AxC\leftarrow C+A_x

对于所有Ax,y=1,Cy=ByA_{x,y}=1,C_y=B_y,将yy加入TT集合

}

由于每个元素最多进入TT集合一次,因此SS中一定不会有重复

这个题的核心在于Ai,i=1A_{i,i}=1

[code]#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 110
using namespace std;
int n,a[M];
char map[M][M];
int q[M],r,h;
int stack[M],top;
int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++)
        scanf("%s",map[i]+1);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(!a[i]) q[++r]=i;
    }
    while(r!=h)
    {
        int x=q[++h];
        stack[++top]=x;
        for(i=1;i<=n;i++)
            if( map[x][i]=='1' && !--a[i] )
                q[++r]=i;
    }
    cout<<top<<endl;
    for(i=1;i<=top;i++)
        printf("%d\n",stack[i]);
    return 0;
}


C.The Game Of Parity

题目大意:给定nn个点,每个点有点权,两个人轮流取,每次只能取走一个点,当剩余kk个点时游戏结束,此时若剩余奇数个点则先手获胜,否则后手获胜,求先手是否必胜

大讨论,注意n=kn=k的情况

[code]#include <cstdio>
int main()
{
    puts("I haven't written this problem. >w<");
    return 0;
}


D.Haar Features

题目大意:给定一个矩阵,每个点有一种颜色(黑/白)和一个点权(未给出),求最少计算矩阵的多少个前缀和可以计算出所有黑点的点权和和所有白点的点权和

题目等价于每次可以选择一个前缀矩形,加上任意值,求最少多少次操作后可以使所有黑点都是11,白点都是−1-1

O(n2m2)O(n^2m^2)大模拟即可

[code]#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 110
using namespace std;
int n,m,ans;
char map[M][M];
int a[M][M];
int main()
{
    int i,j,k,l;
    cin>>n>>m;
    for(i=1;i<=n;i++)
        scanf("%s",map[i]+1);
    for(i=n;i;i--)
        for(j=m;j;j--)
            if(a[i][j]!=(map[i][j]=='B'?1:-1) )
            {
                int temp=(map[i][j]=='B'?1:-1)-a[i][j];
                ans++;
                for(k=1;k<=i;k++)
                    for(l=1;l<=j;l++)
                        a[k][l]+=temp;
            }
    cout<<ans<<endl;
    return 0;
}


E.Sasha Circle

题目大意:给定一些红点和一些蓝点,求是否存在一个圆能将红点和蓝点完全分开

论文题。

[code]#include <cstdio>
#include <algorithm>
int main()
{
    srand(23333333);
    puts(rand()&1?"YES":"NO");
}


F:Yura and Developers

题目大意:给定一个长度为nn的序列,求有多少区间满足区间和−-区间最大值≡0( mod k)≡0(\ mod\ k)

每次选择区间最大值进行分治,可以得到一棵树形结构

用map启发式合并可以做到O(nlog2n)O(nlog^2n)

用数组可以做到O(nlogn)O(nlogn)

具体写法看代码把我也说不清楚

[code]#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
struct Array{
    int a[1001001],tim[1001001],T;
    void Initialize()
    {
        ++T;
    }
    int& operator [] (int x)
    {
        if(tim[x]!=T)
            tim[x]=T,a[x]=0;
        return a[x];
    }
}cnt;
int n,k;
long long ans;
int a[M],sum[M],son[M][2];
int stack[M],top;
void Divide_And_Conquer(int x,int l,int r)
{
    int i;
    if(!x) return ;
    if( x-l < r-x )
    {
        Divide_And_Conquer(son[x][0],l,x-1);
        cnt.Initialize();
        Divide_And_Conquer(son[x][1],x+1,r);
        cnt[sum[x]]++;
        for(i=l-1;i<=x-1;i++)
            ans+=cnt[(sum[i]+a[x])%k];
        cnt[sum[x]]--;
        for(i=l;i<=x;i++)
            cnt[sum[i]]++;
    }
    else
    {
        Divide_And_Conquer(son[x][1],x+1,r);
        cnt.Initialize();
        Divide_And_Conquer(son[x][0],l,x-1);
        cnt[sum[l-1]]++;
        for(i=x;i<=r;i++)
            ans+=cnt[(sum[i]+k-a[x]%k)%k];
        cnt[sum[l-1]]--;
        for(i=x;i<=r;i++)
            cnt[sum[i]]++;
    }
}
int main()
{
    int i;
    cin>>n>>k;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        sum[i]=(sum[i-1]+a[i])%k;
    for(i=1;i<=n;i++)
    {
        while( top && a[stack[top]]<a[i] )
        {
            if( top>=2 && a[stack[top-1]]<a[i] )
                son[stack[top-1]][1]=stack[top];
            else
                son[i][0]=stack[top];
            stack[top--]=0;
        }
        stack[++top]=i;
    }
    for(i=1;i<top;i++)
        son[stack[i]][1]=stack[i+1];
    Divide_And_Conquer(stack[1],1,n);
    cout<<ans-n<<endl;
    return 0;
}


G:Happy Line

题目大意:给定一个序列,每次你可以选择两个相邻的数,将左边的数−1-1,右边的数+1+1,然后交换这两个数

问能否通过操作使得序列单调不减

容易发现,每个元素的大小+位置是不变的

要求最终的序列单调不减,那么位置递增,大小不减,故大小+位置递增

只需要按照大小+位置排个序,然后判断相邻两项是否相同即可

[code]#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
int n,a[M],b[M];
bool Compare(int x,int y)
{
    return x+a[x] < y+a[y] ;
}
int main()
{
    int i;
    cin>>n;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        b[i]=i;
    sort(b+1,b+n+1,Compare);
    for(i=1;i<=n;i++)
        if(a[b[i]]+b[i]-i<0)
            return puts(":("),0;
    for(i=1;i<n;i++)
        if(a[b[i]]+b[i]==a[b[i+1]]+b[i+1])
            return puts(":("),0;
    for(i=1;i<=n;i++)
        printf("%d%c",a[b[i]]+b[i]-i,i==n?'\n':' ');
    return 0;
}


H:Degenerate Matrix

题目大意:给定一个2∗22*2的矩阵AA,定义||A||||A||为AA中所有元素绝对值的最大值,求一个行列式为00的2∗22*2矩阵BB满足||A−B||||A-B||最小

二分答案xx

令A=(a bc d),B=(a′ b′c′ d′)A=\begin{pmatrix}a\ \ \ b\\c\ \ \ d\end{pmatrix},B=\begin{pmatrix}a'\ \ \ b'\\c'\ \ \ d'\end{pmatrix}

那么:

a′∈[a−x,a+x],...a'\in[a-x,a+x],...

现在要求a′d′=b′c′a'd'=b'c'

我们知道若x∈[l1,r1],y∈[l2,r2]x\in[l_1,r_1],y\in[l_2,r_2],那么xy∈[min{l1l2,l1r2,r1l2,r1r2},max{...}]xy\in[min\{l_1l_2,l_1r_2,r_1l_2,r_1r_2\},max\{...\}]

我们只需要判断a′d′a'd'所在区间与b′c′b'c'所在区间有没有交即可

[code]#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define EPS 1e-16
using namespace std;
typedef __float128 ld;
struct Interval{
    ld l,r;
    Interval() {}
    Interval(ld _,ld __):
        l(_),r(__) {}
    friend Interval operator * (const Interval &i1,const Interval &i2)
    {
        ld a1=i1.l*i2.l;
        ld a2=i1.l*i2.r;
        ld a3=i1.r*i2.l;
        ld a4=i1.r*i2.r;
        return Interval(min(min(a1,a2),min(a3,a4)),max(max(a1,a2),max(a3,a4)));
    }
    bool In_Interval(ld x) const
    {
        return x >= l && x <= r ;
    }
    friend bool Have_Intersection(const Interval &i1,const Interval &i2)
    {
        return i1.In_Interval(i2.l) || i1.In_Interval(i2.r) || i2.In_Interval(i1.l) ;
    }
};
long double a,b,c,d;
bool Judge(ld x)
{
    Interval _a(a-x,a+x);
    Interval _b(b-x,b+x);
    Interval _c(c-x,c+x);
    Interval _d(d-x,d+x);
    Interval temp1=_a*_d,temp2=_b*_c;
    return Have_Intersection(temp1,temp2);
}
long double Bisection()
{
    ld l=0,r=1e9;
    for(int i=1;i<=1000;i++)
    {
        ld mid=(l+r)/2;
        if( Judge(mid) )
            r=mid;
        else
            l=mid;
    }
    return (l+r)/2;
}
int main()
{
    cin>>a>>b>>c>>d;
    cout<<fixed<<setprecision(20)<<Bisection()<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: