codeforces 603Div2

D题
并查集搞一搞就过了

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
map<char, int > mp;
int pre[N];
int finds(int x){
	return x == pre[x]? x: pre[x] = finds(pre[x]);
}
void unions(int x, int y){
	int xx = finds(x);
	int yy = finds(y);
	pre[xx] = yy;
}
int vis[N];
int main()
{
 
	int n;
	cin >> n;
	for(int i = 0 ; i <= n ;i ++) pre[i] = i;
	for(int i = 1; i <= n; i ++){
		string s;
		cin >> s;
		for(int j = 0; j < s.size(); j ++){
			if(!mp[s[j]]){
				mp[s[j]] = i;
			}
			else unions(mp[s[j]], i);
		}
	}
 
	int cnt = 0;
	for(int i = 1;i <= n; i ++){
		int x = finds(i);
		if(!vis[x]){
			vis[x] = 1;
			cnt ++;
		}
	}
	cout << cnt << endl;
}

E题
线段树 区间更新 单点查询
合法的括号序列要求前缀和 > = 0 >= 0 >=0所以查询区间最小值,如果小于0那么就是不合法的,另外第n位前缀和一定是0才合法,如果合法只需要找到最大的前缀和就行。线段树直接维护前缀和。

#include <bits/stdc++.h>
using namespace std;
#define ls rt << 1 
#define rs rt << 1|1
const int N = 1e6 + 5;
typedef long long ll;
int sum[N << 2],add[N << 2],minx[N << 2], maxn[N << 2];
void pushdown(int l, int r , int rt){
	if(add[rt]){
		add[ls] += add[rt];
		add[rs] += add[rt];
		minx[rs] += add[rt];
		maxn[rs] += add[rt];
		minx[ls] += add[rt];
		maxn[ls] += add[rt];
		add[rt] = 0;
	}
}
void update(int l, int r, int rt,int L, int R ,int val){
	//cout << L << " " << R << " " << val << endl;
	if(L <= l && r <= R){
		sum[rt] += (r - l)*val;
		add[rt] += val;
		maxn[rt] += val;
		minx[rt] += val;
		return ;
	}
	pushdown(l, r, rt);
	int mid = l + r >> 1;
	if(mid >= L) update(l, mid ,ls, L, R , val);
	if(mid < R) update(mid + 1, r ,rs , L ,R, val);
	maxn[rt] = max(maxn[rs], maxn[ls]);
	minx[rt] = min(minx[rs], minx[ls]);
}
ll queryMax(int l,int r ,int rt ,int L ,int R){
	if(L <= l && r <= R){
		return maxn[rt];
	}
	pushdown(l, r , rt);
	ll ans = -100;
	ll mid = l + r >> 1;
	if(mid >= L) ans = max(ans, queryMax(l, mid, ls, L, R));
	if(mid < R) ans = max(ans, queryMax(mid + 1, r ,rs, L, R));
	return ans;
 
}
ll queryMin(int l, int r, int rt, int L ,int R){
	if(L <= l && r <= R){
		return minx[rt];
	}
	pushdown(l, r , rt);
	ll ans = 100;
	ll mid = l + r >> 1;
	if(mid >= L) ans = min(ans, queryMin(l, mid, ls, L, R));
	if(mid < R) ans = min(ans, queryMin(mid + 1, r ,rs, L, R));
	return ans;
}
ll querySum(int l, int r, int rt ,int pos){
	if(l == r){
		return maxn[rt];
	}
	pushdown(l, r , rt);
	ll ans = 0;
	int mid = l + r >> 1;
	if(mid >= pos) ans= querySum(l, mid, ls,pos);
	if(mid < pos) ans =querySum(mid + 1, r ,rs, pos);
	return ans;
}
int k[N];
int main()
{
	int n;
	cin >> n;
	string s;
	cin >> s;
	int len = 1;
	vector<int> ans;
	int maxn1 = 0;
	for(int i = 0;i < n; i ++){
		
		if(s[i] == '('){
			update(1, n , 1 , len, n , 1 - k[len]);
			k[len] = 1;
		}
		else if(s[i] == ')'){
						update(1, n , 1, len, n , -1 - k[len]);
			k[len] = -1;
		}
		else if(s[i] == 'L'){
			len --;
			if(len <= 0) len = 1;
		}
		else if(s[i] == 'R'){
			len ++;
		}
		else{
			update(1, n ,1,len, n , -k[len]);
			k[len] = 0;
		}
		//cout << queryMin(1, n , 1, 1, n) <<" " << querySum(1, n , 1, n) <<" " << queryMax(1, n ,1 , 1,n)  << endl;
		if(queryMin(1, n , 1, 1, n) >= 0 && querySum(1, n , 1,  n) == 0){
			ans.push_back(queryMax(1, n ,1 , 1,n));
		}
		else ans.push_back(-1);
	}
	for(int i = 0 ; i < ans.size(); i ++){
		cout << ans[i] <<" ";
	}
	cout << endl;
}

F题

大佬博客

#include <bits/stdc++.h>
using namespace std;
const int N = 5005;
std::vector<int> v[2][N];
int l[2][N], r[2][N];
int ans[2][N][N];
int sz[2][N];
int dp[N];
void dfs(int _, int x){
 	if(x != 1) sz[_][x] = 1;
	for(int i = 0 ;i  < v[_][x].size(); i ++){
		int y = v[_][x][i];
		dfs(_, y);
		sz[_][x] += sz[_][y];
		l[_][x] = min(l[_][x], l[_][y]);
		r[_][x] = max(r[_][x], r[_][y]);
	} 
	ans[_][l[_][x]][r[_][x]] = max(ans[_][l[_][x]][r[_][x]], sz[_][x]);
}
int main()
{
	int n;
	cin >> n;
	for(int i = 0 ; i < 2; i ++){
		int a;
		cin >> a;
		for(int j = 0; j <= a; j ++){
			l[i][j] = n + 1;
			r[i][j] = 0;
		}

		for(int j = 2; j <= a; j ++){
			int x;
			cin >> x;
			v[i][x].push_back(j);
		}
		for(int j = 1; j <= n; j ++){
			int x;
			cin >> x;
			l[i][x] = r[i][x] = j;
		}
		dfs(i, 1);
	}
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= i; j ++){
			dp[i] = max(dp[i],dp[j - 1]+max(ans[0][j][i], ans[1][j][i]));
		}
	}
	cout << dp[n] << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值