130324解题报告

这次周赛选的是两次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]);
	else
		des[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掉=。=


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值