CF766 ABCDE

LINK

A 找最长非公共子序列..如果两串不是完全相同 显然就是最长的那个

/** @Date    : 2017-04-15 19:52:34
  * @FileName: 766A.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoundEarlf@gmail.com)
  * @Link    : https://github.com/Lweleth
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

int main()
{
	string a, b;
	cin >> a >> b;
	if(a == b)
		printf("-1\n");
	else printf("%d\n", max(a.length(), b.length()));
    return 0;
}

 

 


 

B 给出一些数 问里面是否存在三个数能构成三角形 排个序遍历一遍即可 递增数列下,连续的三个数是最可能满足条件的情况了

/** @Date    : 2017-04-15 20:01:31
  * @FileName: 766B.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoundEarlf@gmail.com)
  * @Link    : https://github.com/Lweleth
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

int a[N];
int main()
{
	int n;
	while(cin >> n)
	{
		for(int i = 0; i < n; i++)
			scanf("%d", a + i);
		sort(a, a + n);
		int flag = 0;
		for(int i = 1; i < n - 1; i++)
		{
			if(flag)
				break;
			if(a[i] + a[i - 1] > a[i + 1])
				flag = 1;
		}	
		if(flag)
			printf("YES\n");
		else printf("NO\n");
	}
    return 0;
}

 

 


 

题意:给出一字符串,26个字母对应了最大分割长度b['a'~'z'](即分割完长度不超过b[i]),问在里面做分割,满足条件的分割有多少种,并取模1e9+7,以及分割后里面最小的长度。

思路:DP。枚举位置,从该位置向前推,直到不满足条件位置为止,期间不断转移dp[i]+=dp[j - 1],并更新最大数量和最小长度即可

/** @Date    : 2017-04-16 00:27:49
  * @FileName: 766B DP.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoundEarlf@gmail.com)
  * @Link    : https://github.com/Lweleth
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
const int mod = 1e9+7;
char a[1500];
int dp[1500];
int dp2[1500];
int len[50];
int main()
{
	int n;
	while(cin >> n)
	{
		scanf("%s", a + 1);
		for(int i = 0; i < 26; i++)
			scanf("%d", len + i);
		int ma = -1;
		int mi = INF;
		MMF(dp);
		dp[0] = 1;//代表0~i的分割数
		dp2[0] = 0;//代表0~i里的最小分割长度
		for(int i = 1; i <= n; i++)
		{
			dp2[i] = INF;
			mi = INF;
			int le = INF;
			for(int j = i; j >= 1; j--)//枚举所有可能分割的位置
			{
				le = min(le, min(len[a[i] - 'a'], len[a[j]-'a']));//满足分割后字母对应 字符串长度的限制
				if(le < i - j + 1)
					break;
				dp[i] = (dp[i] + dp[j - 1]) % mod;//对每个可分割的位置进行转移
				mi = min(mi, dp2[j - 1]);
				ma = max(ma, i - j + 1);
			}
			dp2[i] = mi + 1;
		}

		printf("%d\n%d\n%d\n", dp[n], ma, dp2[n]);
	}
    return 0;
}

 

 


 

D

题意:给出一些词语间的关系,问里面每个关系是否成立。就是个种类并查集

思路:可以用偏移量写,也可以用秩来写。

/** @Date    : 2017-04-16 16:14:15
  * @FileName: 766D 种类并查集.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoundEarlf@gmail.com)
  * @Link    : https://github.com/Lweleth
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

map<string, int>mir;

int fa[N];
int rk[N];
int n, m, q;

int find(int x)
{
	int df;
	if(fa[x] == x)
		return x;
	df = fa[x];
	fa[x] = find(fa[x]);
	rk[x] = (rk[x] + rk[df]) & 1;
	return fa[x];
}

int join(int x, int y, int f)
{
	int a = find(x);
	int b = find(y);
	//cout << a << "~" << b;
	if(a != b)
	{
		if(f == 3)//判断用
			return 2;

		fa[b] = a;
		rk[b] = (f + rk[x] - rk[y] + 2) % 2;
		return 1;
	}
	else
	{
		int t = (rk[x] - rk[y] + 2) % 2;
		//cout <<"$"<< t << endl;
		if(f == 3)//判断用
			return (t==0);

		if(t == f)
			return 1;
		else 
			return 0;
	}
}
int main()
{
	while(cin >> n >> m >> q)
	{
		mir.clear();
		string x, y;
		int t;
		for(int i = 1; i <= n; i++)
		{
			fa[i] = i, rk[i] = 0;
			cin >> x;
			mir[x] = i;
		}
		for(int i = 0; i < m; i++)
		{
			scanf("%d", &t);
			t -= 1;
			cin >> x >> y;
			int ans = join(mir[x], mir[y], t);
			printf("%s\n", ans?"YES":"NO");
		}
		for(int i = 0; i < q; i++)
		{
			cin >> x >> y;
			int ans = join(mir[x], mir[y], 3);
			if(ans == 2)
				printf("3\n");
			else 
				printf("%d\n", ans?1:2);
		}
	}
    return 0;
}

 

 

 


 

E

题意:给出一棵树,求所有节点和其它节点的距离和(距离和定义为异或和)

思路:对所有节点的值按二进制分解(异或和的性质),枚举所有二进制位,并储存所有节点权值在当前位下1或0,dfs一遍转移所有0和1,最后统计即可。其中dp[i][0]代表以i为根的所有子节点拥有的0个数。那么对于当前节点为now,下一个节点为nextp的异或和为1的情况数为sum += dp[nextp][0]*dp[now][1]+dp[nextp][1]*dp[now][0],最后答案为对每一位 sum * (1 << i) 求和

 

/** @Date    : 2017-04-16 20:55:11
  * @FileName: 766E 树形DP.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoundEarlf@gmail.com)
  * @Link    : https://github.com/Lweleth
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

int n, x, y;
int a[N];
vectorvt[N];
int bit[N];
int dp[N][2];
LL dfs(int s, int pre)
{
	dp[s][0] = dp[s][1] = 0;
	dp[s][bit[s]]++;
	LL sum = bit[s];
	//ans += a[s];
	for(int i = 0; i < vt[s].size(); i++)
	{
		int np = vt[s][i];
		if(np == pre)
			continue;
		sum += dfs(np, s);
		sum += dp[s][0] * dp[np][1] + dp[s][1] * dp[np][0];
		//cout << sum << endl;
		dp[s][bit[s]] += dp[np][0];
		dp[s][bit[s] ^ 1] += dp[np][1];
	}
	return sum;

}


int main()
{
	while(cin >> n)
	{
		MMF(dp);
		LL ans = 0;
		vt[0].clear();
		for(int i = 1; i <= n; i++)
			scanf("%d", a + i), vt[i].clear();
		for(int i = 1; i < n; i++)
		{
			scanf("%d%d", &x, &y);
			vt[x].PB(y);
			vt[y].PB(x);
		}
		for(int i = 0; i < 21; i++)// 对每一位上的1和0进行 统计
		{
			for(int j = 1; j <= n; j++)//对每个节点的数进行分解
			{
				if(a[j] & (1 << i))
					bit[j] = 1;
				else bit[j] = 0;
			}
			ans += dfs(1, 0) * (1 << i);
		}
		
		printf("%lld\n", ans);
	}
    return 0;
}
posted @ 2017-04-19 19:59  Lweleth  阅读(166)  评论(0编辑  收藏  举报