Codeforces Round #394 (Div. 2)

来源:互联网 发布:小额贷款哪个软件最好 编辑:程序博客网 时间:2024/05/16 09:09

链接:http://codeforces.com/contest/761

A题 Dasha and Stairs

题意大概就是给两个数字a和b然后问有没有可能找到一个区间l,r 使得[l,r]之间的奇数的个数是a,偶数的个数是b。

方法就是之间a和b相差不超过1,且至少一个不为0即可。

B题 Dasha and friends

题意大概是给一个环,长度为l,然后上面有n个障碍,现在人物a在环上某一个位置,我们知道a沿着逆时针方向到达每个障碍的距离,人物b(位置与a并不一定一样)在另外一个环上,我们同样知道b沿着逆时针方向到达每个障碍的距离。然后问说,这两个环上的障碍物是否能够重合。


我们其实只要知道相邻障碍之间的距离就行了,相邻的数字做差可以得到,1,到2,2到3 ,3到4 ……等等的距离 ,然后1 到n的距离我们在纸上随便画一下也可以算出来。

然后对比一下这两个数组是否一样就行,用倍增数组的方式模拟一下环即可。

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<stack>#include<queue>#include<iostream>using namespace std;#define  LONG long longconst int   INF=0x3f3f3f3f;const int MOD=1e9+7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10int a[2000];int b[2000];int c[2000];int d[2000];int main(){    int n , l ;    cin>>n>>l;    for(int i = 1; i<= n ;++ i)        scanf("%d",&a[i]) ;    for(int i = 1 ; i <= n ;++ i)        scanf("%d",&b[i]);    for(int i = 1; i < n ;++ i)        c[i ] = a[i + 1] - a[i ] ,        c[i + n ] = c[i ];        c[n] =  l - a[n ] + a[1],        c[n + n ] = c[n];    for(int i = 1 ; i < n ;++ i)        d[i ] = b[i + 1] - b[ i ] ,        d[i + n] = d[i];        d[n] = l - b[n] + b[1] ,        d[n + n] = d[n];    bool judge = false  ;//    for(int i = 1; i<= n ;++ i)printf("%d ",c[i]);cout<<endl;//   for(int i =1; i<= n ;++ i)printf("%d ",d[i]); cout<<endl;    for(int i = 1; i<= n ;++ i)    {        bool tmp = true ;        for(int j = i ; j <= n + i - 1; ++ j)        {            int k;            k =  j;            if(c[ k - i + 1] != d[k])            {                tmp = false ;            }        }        if(tmp )        {            judge = true ;            break ;        }    }    if(judge) cout<<"YES\n";    else cout<<"NO\n";}
C题 Dasha and Password 

题意有点难解释,大概就是给n串字符,每串有m个字符,然后现在有n个指针,每个指针对应一个字符串,指针指向哪个字符,屏幕上就显示哪个字符,也就是说屏幕上一直显示着n个字符。然后这个指针可以移动,同样是环形的,可以从左边第一个向左移动到左边最后一个。 现在问最少移动指针多少次使得屏幕上显示的字符串是一个合法密码。

对于密码的定义是 1,必须含有数字 2,必须含有小写英文字母,3,必须含有'#'   、'&'   、'*'这三个字符中至少一个。题目说保证输入的字符是合法的,也就是肯定能移动到某一个位置使得屏幕上显示的是密码。

看了题目之后有点晕,每次读这些脑洞英文题都是这样。其实仔细分析一下就发现,有3个条件,那么要么就是n个字符已经达到了3个要求,要么就是只达到2个要求,要么就是只达到1一个要求。

如果达到了3个要求就不用管它了直接0就行,如果是2个,那么我们任意确定两个不同类型的字符不动,然后枚举剩下那个让他移动,同样是用倍增来模拟环形。

如果达到的是一个要求,那么确定一个不动的,然后枚举剩下两个让他们去移动,倍增数组模拟即可。

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<stack>#include<queue>#include<iostream>using namespace std;#define  LONG long longconst int   INF=0x3f3f3f3f;const int MOD=1e9+7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10char  str[100][160];bool judge (char a , char b){    if( a<= 'z' && a>='a' && b<= 'z' && b >='a')        return true ;    if( a>= '0' &&a<='9' && b>='0' && b <='9')        return true;    if( (a == '#' || a == '*' || a == '&') && (b == '#' || b =='&' || b== '*'))        return true ;    return false ;}int main(){    int n , m ;    scanf("%d%d",&n,&m);    for(int i =1 ; i<= n ; ++ i)    {        scanf("%s",str[i]+ m + 1);        for(int j = 1 ; j<= m ;++ j)            str[i][j] = str[i][ j + m],            str[i][ j + 2 * m] = str[i][j + m];    }    int ans = 100000;    for(int i = 1; i<= n ; ++ i)    {        for(int j = 1 ; j<= n ;++ j)        {                int p1 = 2 * m + 1 ;                int p2 = 2 * m + 1;                if( i != j  &&!judge( str[i][p1] , str[j][p2] ) )                {                    for(int k = 1; k<= n ;++ k)                    if(k!= i && k != j )                    {                        int p3 = 2 * m + 1;                        int l = p3 - m / 2 ;                        int r = m / 2 + p3 -1 ;                        if( m%2 == 1) r ++ ;                        for(int t = l ; t <= r ;++ t)                        {                            if(!judge( str[k][ t] , str[i][p1] ) && !judge ( str[k][t] , str[j][p2] ) )                                ans = min( ans , abs(t - p3));                        }                    }                }        }    }
//写了5个for也是醉了。。。。。。。    for(int i =1; i<= n ;++ i)    {        int p1 , p2 , p3;        p1 = p2 = p3 = 2 * m + 1;        for(int j = 1 ; j <= n ;++ j)        {            for(int k = 1; k <= n ;++ k)                if( j != k && i != j && i != k)                {                    int l = p3 - m / 2;                    int r = m / 2 + p3 - 1;                    if( m % 2 == 1)r ++;                    for(int t1 = l ;t1 <= r ;++ t1)                    {                        for(int t2 = l ; t2 <= r ;++ t2)                            if(!judge(str[i][p1] , str[j][t1]) && !judge(str[i][p1] , str[k][t2]) && !judge(str[j][t1] , str[k][t2]))                                ans =min(ans , abs(t1 - p2) + abs(t2 - p3));                    }                }        }    }    cout<<ans<<endl;}
D题 Dasha and Very Difficult Problem

大概就是有3个数组 他们的关系是ci = bi - ai ,现在给出a数组和c数组的相对大小关系p。

让我们去求b数组,而且b数组每个数字必须属于[l , r] ;

构造题

我们贪心去做,先对p从小到大排个序。然后令b[1]为l ,顺便求一下c[1],然后从2到n ,c[i]等于c[i-1] + 1,b[i]也可以求出来,这样能够使得b[i]最小,如果b[i]小于l,就把b[i]等于l 就行。然后顺便再把当前的c[i]求一下。如果有大于r的就是-1了;因为这样能够保证b[i]尽量的靠近l;

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<stack>#include<queue>#include<iostream>using namespace std;#define  LONG long longconst int   INF=0x3f3f3f3f;const int MOD=1e9+7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10struct NUM{    int a, p ,b ,c , tmp,id ;}num[100100];bool cmp1(NUM x, NUM y){    return x.id < y.id ;}bool cmp2 (NUM x , NUM y){    return x.p < y.p ;}int main(){    int n , l ,r;    cin>>n>>l>>r;    for(int i =1 ; i <= n; ++ i)        scanf("%d", &num[i].a),        num[i].id = i ;    for(int i = 1; i <= n ;++ i)        scanf("%d" , &num[i].p) ;    sort( num + 1, num + n + 1 , cmp2) ;    num[1].b = l ;    num[1].c = num[1].b - num[1].a ;    bool judge = true ;    for(int i = 2 ; i<= n ;++ i)    {        num[i].c = num[i -1 ].c + 1;        num[i].b = num[i].a + num[i].c ;        if( num [i].b < l)        {            num[i].b = l            ;num[i].c = num[i].b - num[i].a ;        }        if(num[i].b > r )        {            judge = false ;            break ;        }    }    if(!judge ) cout<<-1<<endl;    else    {        sort(num +1 , num + n +1 ,cmp1);        for(int i =1 ;i <= n ;++i)printf("%d ",num[i].b);    }}

E题 Dasha and Puzzle 

题意是给一棵树然后,要求把树放置在笛卡尔坐标上,边需要平行于坐标轴,问能不能按要求把树放在坐标系里,可以的话输出每个点的坐标,只要一个可行解。

首先一开始想到度数大于4的时候肯定是无解的,然后其他好像都有解,于是我一开始就想错了,认为每条边距离为1的时候也都是可行的,于是写了个判断是否可行的dfs,结果一直不行,后来请教了dalao才知道,原来每条边距离为1的时候,有一些情况是无解的,比如四个连在一起的点,且度数均为4时,就是无解的。所以边的距离应该大于1,然后就可以把边延伸的很大就行,总共有30个点,那么令每条边距离=  2^i ( i<=60) 然后i递减就行

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<stack>#include<queue>#include<iostream>using namespace std;#define  LONG long longconst int   INF=0x3f3f3f3f;const int MOD=1e9+7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10int take[100];struct Edge{    int to , next;}edge[10000];int head[100];int tot = 0;LONG  dir[4][2] = {0 , 1 , -1 , 0 , 1 , 0 , 0 , -1};LONG  ans[100][2];int co[100][6] ;LONG sum = 58;void add_edge(int u , int v){    edge[++tot].to = v;    edge[tot].next = head[u];    head[u] = tot ;}void dfs(int pre , int u){    for(int i = head[u]; i != -1 ; i = edge[i].next)    {        int v =  edge[i].to ;        if(v == pre) continue ;        for(int j = 0; j < 4 ;++ j)        {            if(!co[u][j] && !co[v][3-j])            {                ans[v][0] += ans[u][0] +dir[j][0]*(1LL<<(sum));                ans[v][1] += ans[u][1] + dir[j][1]*(1LL<<(sum--));                //cout<<"fuck";                co[u][j] = 1;                co[v][3 - j] = 1;                break;            }        }        dfs( u , v);    }}int main(){    int n;    scanf("%d",&n) ;    clr0(take);    clrI(head);    bool judge = 1;    for(int i = 1; i < n ;++ i)    {        int u , v;        scanf("%d%d",&u,&v);        add_edge(u , v);        add_edge(v , u);        take[u]++ ;        take[v] ++ ;        if(take[u]> 4 ||take[v ] > 4) judge = 0;    }    if(judge)    {        cout<<"YES\n";        clr0(co);        ans[1][0] = 0;        ans[1][0] = 0;        dfs(-1, 1);        for(int i = 1; i<= n ;++ i)printf("%lld %lld\n",ans[i][0],ans[i][1]);    }    else        cout<<"NO\n";}





0 0
原创粉丝点击