Acwing第58场周赛(AK)

4489. 最长子序列

题意:给定一个长度为 n n n严格单调递增的整数序列 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an

序列 a a a 的子序列可以表示为 a i 1 , a i 2 , … , a i p a_{i1},a{i2},…,a{ip} ai1,ai2,,aip,其中 1 ≤ i 1 < i 2 < … < i p ≤ n 1≤i_1<i_2<…<i_p≤n 1i1<i2<<ipn

我们希望找到一个 a a a 的子序列,使得该子序列满足:对于$ j \in[1,p−1] , , a_{i_{j+1}}≤a_{i_{j×2}}$ 恒成立。

我们认为,长度为 1 1 1 的子序列总是满足条件的。

请你计算并输出满足条件的子序列的最大可能长度。

输入格式

第一行包含一个整数 n n n

第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an

输出格式

一个整数,表示满足条件的子序列的最大可能长度。

直觉:二分答案,但是发现题目中说序列是严格单调递增的,也就是没有重复的元素,所以可以考虑贪心。用类似双指针的思路贪心就行,(细节写的不好,调了一段时间)

/*
A: 10min
B: 20min
C: 30min
D: 40min
*/ 
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#define pb push_back 
#define all(x) (x).begin(),(x).end()
#define mem(f, x) memset(f,x,sizeof(f)) 
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
template<typename T>inline void rd(T &a) {
    char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
    while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}

typedef pair<long long ,long long >PII;
typedef pair<long,long>PLL;

typedef long long ll;
typedef unsigned long long ull; 
const int N=2e5+10,M=1e9+7;

ll n,a[N];
ll ans=1;
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;){
		int j = i+1;
		int p = i , q = j;
		bool flag=0;
		while(q<=n && a[q]<=a[p]*2){
			p++,q++;
			flag=1;
		}
		if(flag){
		  //  cout<<i<<" "<<q<<endl;
		    ans = max(ans,(1ll)*(q-i));
		}
			
		i = q;
	}
	cout<<ans;
}

int main(){
    solve();
	return 0;
}

4490. 染色

给定一个 n n n 个节点的树,节点编号为 1 ∼ n 1∼n 1n

1 1 1 号节点是树的根节点。

初始时,所有节点的颜色均为 0 0 0

现在,你需要对该树进行重新染色,其中节点 i i i 的目标颜色为 c i c_i ci

每次染色操作的具体流程如下:

  1. 选择一个节点 v v v 和一种颜色 x x x
  2. 将以节点 v v v 为根节点的子树中的全部节点(包括节点 v v v)都染成颜色 x x x

请你计算,为了使得每个节点都被染成目标颜色,至少需要进行多少次染色操作。

输入格式

第一行包含整数 n n n

第二行包含 n − 1 n−1 n1 个整数 p 2 , p 3 , … , p n p_2,p_3,…,p_n p2,p3,,pn,其中 p i p_i pi 表示节点 i i i 的父节点编号。

第三行包含 n n n 个整数 c 1 , c 2 , … , c n c_1,c_2,…,c_n c1,c2,,cn,其中 c i c_i ci 表示节点 i i i 的目标颜色。

保证输入给定图是一棵树。

输出格式

一个整数,表示最少所需的染色操作次数。

所有测试点满足 2 ≤ n ≤ 1 0 4 2≤n≤10^4 2n104 1 ≤ p i < i 1≤p_i<i 1pi<i 1 ≤ c i ≤ n 1≤c_i≤n 1cin


直觉:dfs遍历,不是树形dp。

发现如果一个子节点的颜色和他的父节点颜色不同的话,一定会进行一次染色。

从父节点向下染色。首先给的当前遍历到的节点染色,如果该节点染成所需要的颜色后和父节点的颜色相同。那么不需要多一次操作,如果不同表面需要从该节点向下染色。

所以dfs需要传入每次父节点需要染成的颜色,还需要每个节点想变成的颜色,初始颜色。

一开始第一步没有先染色,导致调了一段时间,熟练度不够。

/*
A: 10min
B: 20min
C: 30min
D: 40min
*/ 
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#define pb push_back 
#define all(x) (x).begin(),(x).end()
#define mem(f, x) memset(f,x,sizeof(f)) 
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
template<typename T>inline void rd(T &a) {
    char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
    while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}

typedef pair<long long ,long long >PII;
typedef pair<long,long>PLL;

typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+10,M=1e9+7;

int h[N],e[N],ne[N],idx;
int n,fa[N];
int pre[N],col[N],ans;
void add(int a,int b){
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}

void dfs(int u,int Fa,int Col){ // 将u节点和他的子树染成col[u]  
	bool flag=1; 
	pre[u] = Col;
	if(pre[u] != col[u]){ // 当前节点的颜色和需要变成的颜色不同 
		pre[u] = col[u];
		ans++;
		if(col[u] == Col){ // 如果需要变成的颜色和祖宗颜色相同 
			; 
		}
		else{  
			flag=0;
		}
	}
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==Fa)continue;
        if(flag){
        	dfs(j,u,Col);
		}
		else
        	dfs(j,u,pre[u]);
    }
}

void solve(){
    cin>>n;
    memset(h,-1,sizeof h);
    fa[1]=1;
    for(int i=2;i<=n;i++){
        cin>>fa[i];
        add(i,fa[i]);
        add(fa[i],i);
    }
    for(int i=1;i<=n;i++)cin>>col[i];
    dfs(1,-1,col[1]);
    cout<<ans+1;
}

int main(){
    solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值