130324解题报告

来源:互联网 发布:zabbix 监控域名 编辑:程序博客网 时间:2024/05/16 11:00

这次周赛选的是两次CF的题。

分别是168div2 170div2

A.Circle Line 水题

B.New Problem

这道题还是蛮有意思的,因为要注意到因为数据范围小而引起的变化。

但是这题n<= 30, 字符串长度<=20。

所以,最多有30*19个长度为2的子串。

但是长度为2的子串一共有26*26。

26*26 > 30*19。

所以这道题我们就只需要枚举长度1的子串和长度2的子串即可。

char a[100][100];int vis[100];int main(){    int n ;    while(cin >> n )    {        memset(vis,0,sizeof(vis));        for (int i = 0 ;i < n ;i ++){        cin >>a[i];        for (int j = 0 ; j < strlen(a[i]); j ++)        vis[a[i][j] - 'a'] ++;        }        for (int i = 0 ;i < 26; i ++)//枚举长度为1的子串        {            if(!vis[i])            {                char aa = i + 'a';                cout <<aa<<endl;                return 0;            }        }//        for (int i = 0 ;i < n ;i ++)//        cout <<a[i]<<" ";        for (int i = 0 ;i < 26 ;i ++)//枚举长度为2的子串        {            for (int j = 0 ;j < 26 ;j ++)            {                char b[20];                char bb = i + 'a';                char cc = j +'a';                //b.clear();                //cout <<bb <<" "<<cc<<endl;                //b = bb + cc;                b[0]=bb;                b[1]=cc;                b[2] = 0;                //cout <<b <<endl;                bool flag = 0;                for (int k = 0 ;k < n; k ++)                {                    if(strstr(a[k],b) != 0)                    {                        //cout <<b<<" "<<a[k]<<endl;                        flag = 1;                        break;                    }                }                if(!flag)                {                    cout<<b<<endl;                    return 0;                }            }        }    }}
C。Learning Languages

裸并查集。

写的略凌乱。

int man[1000];int lan[1000];int findl(int a){    return lan[a] == a?a:lan[a]=findl(lan[a]);}void unionl(int a,int b ){    a = findl(a);    b = findl(b);    if(a == b)return ;    if(a > b)lan[a] = b;    else        lan[b] = a;}int vis[1000];int main(){    int n , m ;    while(cin >> n >> m)    {        memset(vis,0,sizeof(vis));        for (int i = 0 ; i <= n ; i ++)man[i] = i;        for (int i = 0 ; i <= m ; i ++)lan[i] = i;        for (int i = 0 ; i < n ; i ++)        {            int k ;            scanf("%d",&k);            int pre = 0 ,d;            if(k)            {                cin >> pre;            }            for (int j = 1 ; j < k ; j ++)            {                cin >> d;                if(pre != d)                    unionl(pre,d);//将可以想通的语言合并                pre = d;            }            man[i] = pre;        }        for (int i = 0 ; i < n ; i ++)man[i] = findl(man[i]);//找到这个人属于哪个集合的语言        int ans = 0;        for (int i = 0 ; i < n; i ++)        {            vis[man[i]] ++;//记录各种语言集合的人数        }        if(vis[0])//如果有人什么语言都不会 , 那么这些人都要1的费用学习        ans += vis[0];        for (int i = 1 ; i <= m ; i ++)        {            if(vis[i])ans ++;//记录一共有多少种语言集合 每种花费1将其合并        }        if(vis[0] == n)            cout <<n<<endl;        else            cout <<ans - 1<<endl;    }}

D。

E。

F。水题

G。水题,爆搜即可。

但是我爆搜写的略挫,写了150行。。。凌乱的不行。写这题的时候思路太乱。。

#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cmath>#include <cstring>#include <queue>#include <set>#include <vector>#include <stack>#include <map>#include <iomanip>#define PI acos(-1.0)#define Max 2005#define inf 1<<28#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define FOR(i,s,t) for(int i=(s);i<=(t);++i)#define ll long long#define mem(a,b) memset(a,b,sizeof(a))#define mp(a,b) make_pair(a,b)using namespace std;int n , m ;char Map[100][100];struct kdq{    int x,y;} pp[10000];int check(kdq x,kdq y){    if(x.x == y.x)    {        int m1 = min(x.y,y.y);        int m2 = max(x.y,y.y);        for (int i = m1 + 1 ; i < m2 ; i ++)            if(Map[x.x][i] == 'W')return 0;    }    else if(x.y == y.y)    {        int m1 = min(x.x,y.x);        int m2 = max(x.x,y.x);        for (int i = m1 + 1 ; i < m2 ; i ++)            if(Map[i][x.y] == 'W')return 0;    }    else    {        bool ans1 = 0 ,ans2 = 0;        if(x.x < y.x)        {            if(x.y < y.y)            {                for (int i = x.y ; i <= y.y; i ++)                {                    if(Map[x.x][i] =='W')ans1 = 1;                    if(Map[y.x][i] == 'W')ans2 = 1;                }                for (int i = x.x ; i <= y.x ; i ++)                {                    if(Map[i][x.y] == 'W')ans2 =1 ;                    if(Map[i][y.y] == 'W')ans1 = 1;                }                if(ans1 &&ans2 )return 0;            }            else            {                for (int i  = y.y ; i <= x.y ; i ++)                {                    if(Map[x.x][i] =='W')ans1 = 1;                    if(Map[y.x][i] == 'W')ans2 = 1;                }                for (int i = x.x ; i <= y.x ; i ++)                {                    if(Map[i][x.y] == 'W')ans2 =1 ;                    if(Map[i][y.y] == 'W')ans1 = 1;                }                if(ans1 &&ans2 )return 0;            }        }        else        {            if(x.y < y.y)            {                for (int i = x.y ; i <= y.y; i ++)                {                    if(Map[x.x][i] =='W')ans1 = 1;                    if(Map[y.x][i] == 'W')ans2 = 1;                }                for (int i = y.x ; i <= x.x ; i ++)                {                    if(Map[i][x.y] == 'W')ans2 = 1;                    if(Map[i][y.y] == 'W')ans1 = 1;                }                if(ans1 && ans2 )return 0;            }            else            {                for (int i = y.x ; i <= x.x ; i ++)                {                    if(Map[i][x.y] == 'W')ans1 =1 ;                    if(Map[i][y.y] == 'W')ans2 = 1;                }                for (int i = y.y ; i <= x.y; i ++)                {                    if(Map[x.x][i] == 'W')ans2 = 1;                    if(Map[y.x][i] == 'W')ans1 =1 ;                }                if(ans1 && ans2 )return 0;            }        }    }    return 1;}int main(){    cin >> n >> m;    int num = 0;    for (int i = 0 ; i < n ; i ++)    {        scanf("%s",Map[i]);        for (int j = 0 ; j < m ; j ++)        {            if(Map[i][j] == 'B')            {                pp[num ].x = i,pp[num  ].y = j;                num ++;            }        }    }    bool flag = 0 ;    for (int i = 0 ; i < num ; i ++)    {        for (int j = i + 1 ; j < num ; j ++)        {            if(check(pp[i],pp[j]) == 0)                flag = 1;        }        if(flag)break;    }    if(!flag)        cout <<"YES"<<endl;    else        cout <<"NO"<<endl;}

H。贪心。

I。Zero Tree

题意:给你一棵树,有n个节点, n-1 条边,每个节点有一个值。

有一个操作,选择一颗包含节点1的子树,这棵子树可以加1或者减1

问最少经过多少次操作,使所有节点的值为0。

思路:我们可以将这棵树看成以节点1 为祖先的一棵树。每次都搜到根节点,每次从节点1到这个根节点之间的子树,根据根节点的值进行加减,处理完之后,这个根节点就不需要使用了,其他子树也不会包括这个根节点。

那么显然,可以用递归实现,搜到根节点,然后层层更新。最后更新到节点1,输出节点1加减的值即为总值。

vector<int>q[Max];__int64 value[Max];__int64 add[Max];__int64 des[Max];int max(int a,int b){return a>b?a:b;}void dfs(int now, int pre){for (int i = 0 ;i < q[now].size(); i ++){int next = q[now][i];if(next != pre){dfs(next,now);add[now] = max(add[now], add[next]);des[now] = max(des[now], des[next]);}}value[now] = value[now] + add[now] - des[now];if(value[now] < 0)add[now] += -(value[now]);elsedes[now] += value[now];}int main(){int n ;cin >> n ;int a,b;for (int i = 0 ;i < n - 1 ; i++){scanf("%d%d",&a,&b);q[b].push_back(a);q[a].push_back(b);}for (int i = 1; i <= n ; i++)scanf("%I64d",&value[i]);dfs(1,-1);cout << add[1] + des[1] <<endl;}
这算是上周的任务了。。

明天还得继续把今天周赛的题给A掉=。=


原创粉丝点击