这次周赛选的是两次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掉=。=